2012-12-21 37 views
20

我有一個<pandas.core.groupby.SeriesGroupBy object at 0x03F1A9F0>類型的時間系列對象groupedgrouped.sum()給出了所需的結果,但我無法使rolling_sum與groupby對象一起使用。有沒有辦法將滾動功能應用於groupby對象?例如:Python - 用於GroupBy對象的滾動函數

x = range(0, 6) 
id = ['a', 'a', 'a', 'b', 'b', 'b'] 
df = DataFrame(zip(id, x), columns = ['id', 'x']) 
df.groupby('id').sum() 
id x 
a 3 
b 12 

不過,我想有這樣的:

id x 
0 a 0 
1 a 1 
2 a 3 
3 b 3 
4 b 7 
5 b 12 
+0

您究竟如何期望滾動功能在分組對象上工作(我的意思是寫出數學y你想在符號中做)? – tacaswell

+0

對不起,我應該更清楚。 – ezbentley

+0

所以你想在每個組上做一個'cumsum',然後將整個事情縫合到一個單一的數據框中? – tacaswell

回答

25
In [16]: df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1) 
Out[16]: 
0 0.0 
1 0.5 
2 1.5 
3 3.0 
4 3.5 
5 4.5 

In [17]: df.groupby('id')['x'].cumsum() 
Out[17]: 
0  0 
1  1 
2  3 
3  3 
4  7 
5 12 
+8

pd.rolling_mean現在已棄用系列,將被刪除,使用'df.groupby('id')['x']。rolling(2).mean()'而不是 – kekert

1

我不知道的機制,但這個工程。請注意,返回的值只是一個ndarray。我認爲你可以以這種方式應用任何累積或「滾動」功能,它應該有相同的結果。

我用cumprod,cummaxcummin進行了測試,他們都返回了一個ndarray。我認爲熊貓足夠聰明,知道這些函數會返回一系列的函數,所以函數作爲一種轉換而不是聚合來應用。

In [35]: df.groupby('id')['x'].cumsum() 
Out[35]: 
0  0 
1  1 
2  3 
3  3 
4  7 
5 12 

編輯:我發現它奇怪的是,這個語法確實返回系列:

In [54]: df.groupby('id')['x'].transform('cumsum') 
Out[54]: 
0  0 
1  1 
2  3 
3  3 
4  7 
5 12 
Name: x 
22

對於誰臨到這個老問題的Google:

關於@ kekert的評論@加勒特的答案使用新的

df.groupby('id')['x'].rolling(2).mean() 

,而不是現在不推薦使用

df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1) 

奇怪的是,似乎新.rolling()。意思是()方法返回一個多索引的系列,由GROUP_BY列索引,然後再索引。而舊的方法只是簡單地返回一個由原始df索引單獨索引的序列,這可能意義不大,但是將該序列作爲新的列添加到原始數據框中非常方便。

所以我想我已經想通了,採用了新的軋()方法,並仍然是一個解決方案的工作原理相同:

df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True) 

這應該給你一系列

0 0.0 
1 0.5 
2 1.5 
3 3.0 
4 3.5 
5 4.5 

你可以添加爲一列:

df['x'] = df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True) 
+0

我想你可以使用'.transform'而不是reset_index? – TMrtSmith

+1

如果您按多列分組,這實際上會失敗。刪除第一個參數(級別)可以解決此問題,因爲它會默認刪除所有級別。(2).mean()。reset_index(drop = True)'df ['x'] = df.groupby('id')['x']。 –