[英]Pandas groupby cumulative sum
我想在我的 Pandas dataframe 中添加一個累積總和列,以便:
姓名 | 天 | 不 |
---|---|---|
傑克 | 周一 | 10 |
傑克 | 周二 | 20 |
傑克 | 周二 | 10 |
傑克 | 周三 | 50 |
吉爾 | 周一 | 40 |
吉爾 | 周三 | 110 |
變成:
Jack | Monday | 10 | 10
Jack | Tuesday | 30 | 40
Jack | Wednesday | 50 | 90
Jill | Monday | 40 | 40
Jill | Wednesday | 110 | 150
我嘗試了df.groupby
和df.agg(lambda x: cumsum(x))
的各種組合,但無濟於事。
這應該可以,需要groupby()
兩次:
df.groupby(['name', 'day']).sum() \
.groupby(level=0).cumsum().reset_index()
解釋:
print(df)
name day no
0 Jack Monday 10
1 Jack Tuesday 20
2 Jack Tuesday 10
3 Jack Wednesday 50
4 Jill Monday 40
5 Jill Wednesday 110
# sum per name/day
print( df.groupby(['name', 'day']).sum() )
no
name day
Jack Monday 10
Tuesday 30
Wednesday 50
Jill Monday 40
Wednesday 110
# cumulative sum per name/day
print( df.groupby(['name', 'day']).sum() \
.groupby(level=0).cumsum() )
no
name day
Jack Monday 10
Tuesday 40
Wednesday 90
Jill Monday 40
Wednesday 150
由第一個總和產生的數據幀由'name'
和'day'
索引。 你可以通過打印看到它
df.groupby(['name', 'day']).sum().index
在計算累積總和時,您希望通過'name'
,對應於第一個索引(級別 0)。
最后,使用reset_index
使名稱重復。
df.groupby(['name', 'day']).sum().groupby(level=0).cumsum().reset_index()
name day no
0 Jack Monday 10
1 Jack Tuesday 40
2 Jack Wednesday 90
3 Jill Monday 40
4 Jill Wednesday 150
這適用於熊貓 0.16.2
In[23]: print df
name day no
0 Jack Monday 10
1 Jack Tuesday 20
2 Jack Tuesday 10
3 Jack Wednesday 50
4 Jill Monday 40
5 Jill Wednesday 110
In[24]: df['no_cumulative'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
In[25]: print df
name day no no_cumulative
0 Jack Monday 10 10
1 Jack Tuesday 20 30
2 Jack Tuesday 10 40
3 Jack Wednesday 50 90
4 Jill Monday 40 40
5 Jill Wednesday 110 150
修改@Dmitry 的回答。 這更簡單,適用於 Pandas 0.19.0:
print(df)
name day no
0 Jack Monday 10
1 Jack Tuesday 20
2 Jack Tuesday 10
3 Jack Wednesday 50
4 Jill Monday 40
5 Jill Wednesday 110
df['no_csum'] = df.groupby(['name'])['no'].cumsum()
print(df)
name day no no_csum
0 Jack Monday 10 10
1 Jack Tuesday 20 30
2 Jack Tuesday 10 40
3 Jack Wednesday 50 90
4 Jill Monday 40 40
5 Jill Wednesday 110 150
你應該使用
df['cum_no'] = df.no.cumsum()
http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.cumsum.html
另一種方法
import pandas as pd
df = pd.DataFrame({'C1' : ['a','a','a','b','b'],
'C2' : [1,2,3,4,5]})
df['cumsum'] = df.groupby(by=['C1'])['C2'].transform(lambda x: x.cumsum())
df
而不是df.groupby(by=['name','day']).sum().groupby(level=[0]).cumsum()
(見上文)你也可以做一個df.set_index(['name', 'day']).groupby(level=0, as_index=False).cumsum()
df.groupby(by=['name','day']).sum()
實際上只是將兩列移動到 MultiIndexas_index=False
意味着您之后不需要調用 reset_index數據.csv:
name,day,no
Jack,Monday,10
Jack,Tuesday,20
Jack,Tuesday,10
Jack,Wednesday,50
Jill,Monday,40
Jill,Wednesday,110
代碼:
import numpy as np
import pandas as pd
df = pd.read_csv('data.csv')
print(df)
df = df.groupby(['name', 'day'])['no'].sum().reset_index()
print(df)
df['cumsum'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
print(df)
輸出:
name day no
0 Jack Monday 10
1 Jack Tuesday 20
2 Jack Tuesday 10
3 Jack Wednesday 50
4 Jill Monday 40
5 Jill Wednesday 110
name day no
0 Jack Monday 10
1 Jack Tuesday 30
2 Jack Wednesday 50
3 Jill Monday 40
4 Jill Wednesday 110
name day no cumsum
0 Jack Monday 10 10
1 Jack Tuesday 30 40
2 Jack Wednesday 50 90
3 Jill Monday 40 40
4 Jill Wednesday 110 150
從 1.0 版開始,pandas 為 window 功能獲得了新的 api。
具體來說,早先取得的成就
df.groupby(['name'])['no'].apply(lambda x: x.cumsum())
或者
df.set_index(['name', 'day']).groupby(level=0, as_index=False).cumsum()
現在變成
df.groupby(['name'])['no'].expanding().sum()
我發現所有與窗口相關的功能都比 groupby+level 操作更直觀
盡管學習使用 groupby 對於一般用途很有用。
請參閱文檔: https://pandas.pydata.org/docs/user_guide/window.html
如果你想寫一個單線(也許你想將方法傳遞到管道中),你可以通過首先將groupby
方法的as_index
參數設置為 False 以從聚合步驟返回 dataframe 並使用assign()
來實現為其分配一個新列(每個人的累積總和)。
這些鏈接的方法返回一個新的 dataframe,因此您需要將其分配給一個變量(例如agg_df
)以便以后能夠使用它。
agg_df = (
# aggregate df by name and day
df.groupby(['name','day'], as_index=False)['no'].sum()
.assign(
# assign the cumulative sum of each name as a new column
cumulative_sum=lambda x: x.groupby('name')['no'].cumsum()
)
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.