熊猫-Groupby两个功能

时间:2018-10-15 09:04:54

标签: python pandas pandas-groupby

我一直试图在熊猫groupby对象上获得一个积木。我需要将cumsum移位一位,这是通过shift()实现的。但是,在单个groupby对象上同时执行这两项功能会产生一些不良结果:

df = pd.DataFrame({'A': [1, 1, 1, 2, 2, 2],
                   'B': [2, 3, 5, 2, 3, 5]})

df.groupby('A').cumsum().shift()

给出:

      B
0   NaN
1   2.0
2   5.0
3  10.0
4   2.0
5   5.0

即组1上的cumsum()的最后一个值移到组2的第一个值。我要这些组保持分隔,并得到:

      B
0   NaN
1   2.0
2   5.0
3   NaN
4   2.0
5   5.0

但是我不确定如何使这两个函数在groupby对象上组合工作。在其他任何地方都找不到此问题。一直在玩agg,但似乎无法解决。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

lambda functionGroupBy.apply一起使用,也有必要在groupby之后定义列表中的列以进行处理:

df['B'] = df.groupby('A')['B'].apply(lambda x: x.cumsum().shift())
print (df)
   A    B
0  1  NaN
1  1  2.0
2  1  5.0
3  2  NaN
4  2  2.0
5  2  5.0

答案 1 :(得分:1)

first 操作df.groupby('A').cumsum()的结果是常规数据帧。它等效于df.groupby('A')[['B']].cumsum(),但是Pandas方便地省略了[['B']]索引部分。

因此,默认情况下,将不会 对该数据帧进行任何后续操作,除非您再次使用GroupBy

res = df.groupby('A').cumsum().groupby(df['A']).shift()

但是,正如您所看到的,这将重复分组操作,并且效率很低。您可以定义一个单个函数,该函数以正确的顺序组合cumsumshift,然后将此函数应用于单个GroupBy对象。定义单个函数称为function composition,它不是Python固有的。这里有一些替代方法:

定义一个新的命名函数

这是一个明确的建议解决方案:

def cum_shift(x):
    return x.cumsum().shift()

res1 = df.groupby('A')[['B']].apply(cum_shift)

定义匿名lambda函数

上述内容的单行版本:

res2 = df.groupby('A')[['B']].apply(lambda x: x.cumsum().shift())

使用由图书馆组成的图书馆

这是一个纯粹的功能解决方案;例如,通过第三方toolz

from toolz import compose
from operator import methodcaller

cumsum_shift_comp = compose(methodcaller('shift'), methodcaller('cumsum'))

res3 = df.groupby('A')[['B']].apply(cumsum_shift_comp)

以上所有均给出相同的结果:

assert res.equals(res1) and res1.equals(res2) and res2.equals(res3)

print(res1)

     B
0  NaN
1  2.0
2  5.0
3  NaN
4  2.0
5  5.0