Python-GroupBy对象的滚动函数

Python-GroupBy对象的滚动函数,python,pandas,pandas-groupby,rolling-computation,rolling-sum,Python,Pandas,Pandas Groupby,Rolling Computation,Rolling Sum,我有一个时间序列对象分组,类型为grouped.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

我有一个时间序列对象
分组
,类型为
grouped.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

我不确定机械原理,但这是可行的。注意,返回的值只是一个ndarray。我认为你可以用这种方式应用任何累积或“滚动”函数,它应该有相同的结果

我用
cumprod
cummax
cummin
对它进行了测试,它们都返回了一个数据数组。我认为pandas足够聪明,知道这些函数返回一个序列,因此该函数被用作转换而不是聚合

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
累计金额 为了直接回答这个问题,cumsum方法将生成所需的序列:

In [17]: df
Out[17]:
  id  x
0  a  0
1  a  1
2  a  2
3  b  3
4  b  4
5  b  5

In [18]: df.groupby('id').x.cumsum()
Out[18]:
0     0
1     1
2     3
3     3
4     7
5    12
Name: x, dtype: int64
每组的滚动函数 更一般地说,任何滚动函数都可以应用于每个组,如下所示(使用@kekert注释的新的.rolling方法)。请注意,返回类型是一个多索引系列,它不同于以前的(不推荐的)pd.rolling方法

In [10]: df.groupby('id')['x'].rolling(2, min_periods=1).sum()
Out[10]:
id
a   0   0.00
    1   1.00
    2   3.00
b   3   3.00
    4   7.00
    5   9.00
Name: x, dtype: float64
要应用分组滚动功能并以原始数据帧顺序接收结果,应使用转换:

In [16]: df.groupby('id')['x'].transform(lambda s: s.rolling(2, min_periods=1).sum())
Out[16]:
0    0
1    1
2    3
3    3
4    7
5    9
Name: x, dtype: int64

不推荐的方法 以下是现在不推荐使用的pandas.rolling_mean的行为,仅供参考:

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

对于遇到这个老问题的谷歌人来说:

关于@kekert对@Garrett使用新

df.groupby('id')['x'].rolling(2).mean()
而不是现在被弃用的

df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1)
奇怪的是,新的.rolling().mean()方法似乎返回一个多索引序列,首先由组按列索引,然后由索引索引。然而,旧的方法只是返回一个由原始df索引单独索引的序列,这可能没有什么意义,但它非常方便地将该序列作为新列添加到原始数据帧中

因此,我想我已经找到了一个使用新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)

这是另一种很好地概括并使用pandas方法的方法

它非常有效,而且对于固定窗口(如时间序列)也非常有效

# 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

如果需要将分组滚动函数重新分配回原始数据帧,同时保持顺序和分组,则可以使用
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())

你到底希望滚动函数在分组对象上如何工作(我的意思是用符号写出你想做的数学)?对不起,我应该说得更清楚。所以你想在每个分组上做一个
cumsum
,然后将整件事缝合回一个数据帧中?是的,理想情况下是cumsum和任何滚动函数(mean,sum,std).pd.rolling\u-mean现在不推荐用于Series,将被删除,请使用
df.groupby('id')['x'].rolling(2).mean()
instead我认为您可以使用
.transform
而不是重置\u-index?如果您按多个列进行分组,这实际上会失败。删除第一个参数(levels)可以解决这个问题,因为默认情况下它会删除所有级别。因此,该行变为
df['x']=df.groupby('id')['x']].rolling(2).mean().reset_index(drop=True)
如果您的组变量尚未排序,则使用
groupby(…,sort=False)
。当我将这个滚动平均值作为一个新列添加时,我得到了非常奇怪的结果,因为顺序与原始df不匹配。非常有用的信息。a) 他们应该将此添加到他们的b)你能提出一些关于功能更改的错误吗?在他们提出异议之前,他们应该更好地考虑后果。你能详细说明为什么我们应该把<代码>滚动(2)< /代码>,即为什么代码>窗口=2 < /代码>?是否因为有两组“a”和“b”?您是否有任何证据证明这是“非常有效的”?一般来说,与向量运算(内置的“.sum”、“.rolling”等)相比,使用pandas进行任何类型的迭代(例如“transform”或“apply”)都会对性能造成重大影响。我知道Pandas确实会对迭代循环进行一些预检查,看看它是否可以为您优化它,但一般来说,如果性能是一个问题,则应该避免迭代。很抱歉,我只能给您一票赞成票,我正在考虑创建新帐户,以便为这个答案提供更多的信任。这是唯一一个对我有效的多栏分组,谢谢!酷。这可以应用指数移动平均
q['exponential_ave']=q.groupby('id')['x'].transform(lambda x:x.ewm(com=0.2).mean())