Python - GroupBy对象的滚动函数

时间:2012-12-21 19:49:00

标签: python pandas

我有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

5 个答案:

答案 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。我认为你可以用这种方式应用任何累积或“滚动”功能,它应该有相同的结果。

我已使用cumprodcummaxcummin对其进行了测试,他们都返回了一个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())