Python - GroupBy对象的滚动函数

40 python pandas rolling-computation rolling-sum pandas-groupby

我有一个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
Run Code Online (Sandbox Code Playgroud)

但是,我希望有类似的东西:

  id  x
0  a  0
1  a  1
2  a  3
3  b  3
4  b  7
5  b  12
Run Code Online (Sandbox Code Playgroud)

Kev*_*ang 74

对于遇到这个老问题的Google员工:

关于@kekert对@Garrett使用新的答案的评论

df.groupby('id')['x'].rolling(2).mean()
Run Code Online (Sandbox Code Playgroud)

而不是现在已弃用的

df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)
Run Code Online (Sandbox Code Playgroud)

奇怪的是,似乎新的.rolling().mean()方法返回一个多索引序列,首先由group_by列索引,然后索引索引.然而,旧方法将简单地返回由原始df索引单独索引的系列,这可能没有多大意义,但是使得将该系列作为新列添加到原始数据帧中非常方便.

所以我想我已经找到了一个使用新的rolling()方法的解决方案,但仍然可以正常工作:

df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True)
Run Code Online (Sandbox Code Playgroud)

哪个应该给你系列

0    0.0
1    0.5
2    1.5
3    3.0
4    3.5
5    4.5
Run Code Online (Sandbox Code Playgroud)

您可以将其添加为列:

df['x'] = df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True)
Run Code Online (Sandbox Code Playgroud)

  • 如果您按多列分组,则实际上会失败.删除第一个参数(级别)可以解决这个问题,因为默认情况下会删除所有级别.因此该行变为`df ['x'] = df.groupby('id')['x'].rolling(2).mean().reset_index(drop = True) (13认同)
  • 如果您的组变量尚未排序,请使用`groupby(...,sort = False)`作为另一个令人生畏的细微差别。当将此滚动平均值添加为新列时,我得到了非常奇怪的结果,因为该顺序与原始df不匹配。 (5认同)

Gar*_*ett 37

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
Run Code Online (Sandbox Code Playgroud)

  • pd.rolling_mean现在已被弃用,系列将被删除,请使用`df.groupby('id')['x'].rolling(2).mean()` (35认同)

Sea*_*thy 10

这是另一种可以很好地概括并使用熊猫的扩展方法的方法。

它非常有效,也非常适合具有固定窗口的滚动窗口计算,例如时间序列。

# Import pandas library
import pandas as pd

# Prepare columns
x = range(0, 6)
id = ['a', 'a', 'a', 'b', 'b', 'b']

# Create dataframe from columns above
df = pd.DataFrame({'id':id, 'x':x})

# Calculate rolling sum with infinite window size (i.e. all rows in group) using "expanding"
df['rolling_sum'] = df.groupby('id')['x'].transform(lambda x: x.expanding().sum())

# Output as desired by original poster
print(df)
  id  x  rolling_sum
0  a  0            0
1  a  1            1
2  a  2            3
3  b  3            3
4  b  4            7
5  b  5           12
Run Code Online (Sandbox Code Playgroud)