我有grouped
类型的时间序列对象<pandas.core.groupby.SeriesGroupBy object at 0x03F1A9F0>
。 grouped.sum()
给出了所需的结果,但我无法使用rolling_sum来处理groupby
对象。有没有办法将滚动函数应用于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 :(得分:61)
对于遇到这个老问题的Google员工:
关于@kekert对@ Garrett使用新
的回答的评论df.groupby('id')['x'].rolling(2).mean()
而不是现已弃用的
df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)
奇怪的是,似乎新的.rolling()。mean()方法返回一个多索引系列,首先由group_by列索引,然后索引索引。然而,旧的方法只会返回一个由原始df索引单独索引的系列,这可能没什么意义,但是将该系列作为新列添加到原始数据框中非常方便。
所以我认为我已经找到了一个使用new rolling()方法的解决方案,但仍然可以使用相同的方法:
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)
答案 1 :(得分:31)
注意:由@kekert确定,以下pandas模式已被弃用。请参阅以下答案中的当前解决方案。
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
答案 2 :(得分:4)
这是另一种很好推广的方法,它使用了熊猫的expanding方法。
这是非常有效的方法,并且还与固定时间窗口的rolling window calculations完美配合,例如时间序列。
array type has incomplete element type
答案 3 :(得分:2)
我不确定机制,但这很有效。注意,返回的值只是一个ndarray。我认为你可以用这种方式应用任何累积或“滚动”功能,它应该有相同的结果。
我已使用cumprod
,cummax
和cummin
对其进行了测试,他们都返回了一个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
答案 4 :(得分:1)
如果您需要将分组滚动功能重新分配回原始数据帧,同时保持顺序和分组,则可以使用transform
函数。
df.sort_values(by='date', inplace=True)
grpd = df.groupby('group_key')
#using center=false to assign values on window's last row
df['val_rolling_7_mean'] = grpd['val'].transform(lambda x: x.rolling(7, center=False).mean())