在pandas系列中使用先前“行”的值

5
我有一个CSV文件,看起来像这样(当使用read_csv()将其导入pandas Dataframe时,它看起来也是这样的)。

enter image description here

我希望根据以下逻辑更新列ad_requests中的值:

对于给定的行,如果ad_requests有一个值,则保持不变。否则,将其设置为上一行的ad_requests值减去上一行的impressions。因此,在第一个示例中,我们希望最终得到:

enter image description here

我部分地到达了那里:

df["ad_requests"] = [i if not pd.isnull(i) else ??? for i in df["ad_requests"]]

这就是我卡住的地方。在 else 后面,我想要“返回”并访问之前的“行”,尽管我知道这不是 pandas 的正确用法。 还有一点需要注意的是,行始终以列 ad_tag_name 为三个一组。如果我使用 pd.groupby["ad_tag_name"],那么我就可以将其转换为一个列表,并开始切片和索引,但我认为在 pandas 中必须有更好的方法(因为有很多东西)。

Python: 2.7.10

Pandas: 0.18.0


1
提示:df.ad_requests.ffill() - df.impressions.cumsum().shift() 可以帮助你完成部分工作。 - John Zwinck
有趣。使用这种方法,前几行空白行的值略有偏差,最终变成负数: http://imgur.com/a/k7faf - Pyderman
这就是为什么它是提示而不是完整的解决方案。cumsum 需要在 ad_requests 不为零时每次重置为 0,或者类似的操作。 - John Zwinck
1个回答

3
您需要做类似于这样的事情:

您需要像这样做:

pd.options.mode.chained_assignment = None #suppresses "SettingWithCopyWarning"
for index, elem in enumerate(df['ad_requests']):
    if pd.isnull(elem):
        df['ad_requests'][index]=df['ad_requests'][index-1]-df['impressions'][index-1]

警告是因为我们正在更改数据框的视图的值,这影响了原始数据框。然而,这正是我们想要做的,所以这并不关系我们。

(Python 2.7.12和Pandas 0.19.0)

编辑:

将代码的最后一行更改为

df['ad_requests'][index]=df['ad_requests'][index-1]-df['impressions'][index-1]

to

df.at[index,'ad_requests']=df.at[index-1,'ad_requests']-df.at[index-1,'impressions']

消除了抑制任何警告的需要:

for index, elem in enumerate(df['ad_requests']):
    if pd.isnull(elem):
        df.at[index,'ad_requests']=df.at[index-1,'ad_requests']-df.at[index-1,'impressions']

1
我知道我需要以某种方式使用前面元素的索引,但我忘记了 enumerate() 。而且我知道最终解决方案将会非常简短和整洁,因为大多数基于pandas的解决方案都是如此。感谢您提供这种优雅的方法。 - Pyderman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接