use*_*956 5 python dataframe pandas cumsum
我有一个像这样的数据框:
customer spend hurdle
A 20 50
A 31 50
A 20 50
B 50 100
B 51 100
B 30 100
Run Code Online (Sandbox Code Playgroud)
我要计算“累积”的其他列,当“累积”总和大于或等于障碍时,该列将基于同一客户重置,如下所示:
customer spend hurdle Cumulative
A 20 50 20
A 31 50 51
A 20 50 20
B 50 100 50
B 51 100 101
B 30 100 30
Run Code Online (Sandbox Code Playgroud)
我在熊猫中使用cumsum和groupby,但我不知道如何根据情况重设它。
以下是我当前使用的代码:
df1['cum_sum'] = df1.groupby(['customer'])['spend'].apply(lambda x: x.cumsum())
Run Code Online (Sandbox Code Playgroud)
我知道这只是正常的累计金额。非常感谢您的帮助。
可能有更快、更有效的方法。这是一种低效的apply方法。
In [3270]: def custcum(x):
...: total = 0
...: for i, v in x.iterrows():
...: total += v.spend
...: x.loc[i, 'cum'] = total
...: if total >= v.hurdle:
...: total = 0
...: return x
...:
In [3271]: df.groupby('customer').apply(custcum)
Out[3271]:
customer spend hurdle cum
0 A 20 50 20.0
1 A 31 50 51.0
2 A 20 50 20.0
3 B 50 100 50.0
4 B 51 100 101.0
5 B 30 100 30.0
Run Code Online (Sandbox Code Playgroud)
您可以考虑使用cython或numba加快custcum
[更新]
Ido回答的改进版本。
In [3276]: s = df.groupby('customer').spend.cumsum()
In [3277]: np.where(s > df.hurdle.shift(-1), s, df.spend)
Out[3277]: array([ 20, 51, 20, 50, 101, 30], dtype=int64)
Run Code Online (Sandbox Code Playgroud)
一种方法是下面的代码。但这确实是一种低效且不优雅的说法。
df1.groupby('customer').apply(lambda x: (x['spend'].cumsum() *(x['spend'].cumsum() > x['hurdle']).astype(int).shift(-1)).fillna(x['spend']))
Run Code Online (Sandbox Code Playgroud)