Результатом вашей первой операции df.groupby('A').cumsum()
является обычный фрейм данных.Это эквивалентно df.groupby('A')[['B']].cumsum()
, но Pandas удобно позволяет вам пропустить индексную часть [['B']]
.
Поэтому любая последующая операция с этим фреймом данных не будет по умолчанию выполняться в группе, если тольковы используете GroupBy
снова :
res = df.groupby('A').cumsum().groupby(df['A']).shift()
Но, как вы можете видеть, это повторяет операцию группировки и будет неэффективным.Вместо этого вы можете определить одну функцию, которая объединяет cumsum
и shift
в правильном порядке, а затем применить эту функцию к одному GroupBy
объекту.Определение этой единственной функции известно как композиция функции , и она не является родной для 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