pandas按组计算的移动平均数错误

pandas moving average by group calculation is wrong

我的数据框 priceDF 是这样开始的:

    Date        symbol  Close
0   2000-01-03  HELN.SW 28.28
1   2000-01-04  HELN.SW 27.50
2   2000-01-05  HELN.SW 26.71
3   2000-01-06  HELN.SW 27.16
4   2000-01-07  HELN.SW 27.50

要计算收盘价的移动平均线,我按交易品种分组:

priceDF['avg'] = priceDF.groupby('symbol')'Close'].rolling(3).mean().reset_index(drop=True)

我得到:

    Date        symbol  Close   avg
0   2000-01-03  HELN.SW 28.28   NaN
1   2000-01-04  HELN.SW 27.50   NaN
2   2000-01-05  HELN.SW 26.71   12.537398
3   2000-01-06  HELN.SW 27.16   12.022164
4   2000-01-07  HELN.SW 27.50   11.922733

在第 2 行中,我想要 avg = 27.50,即第 0 行到第 2 行中收盘价的平均值。 我误解了什么?

我很确定这是这里使用 reset_index 的问题,与多个组一起使用。让我们考虑一个稍微扩展的例子:

from io import StringIO

data = StringIO(
'''
   Date        symbol  Close
0   2000-01-03  HELN.SW 28.28
1   2000-01-04  HELN.SW 27.50
2   2000-01-05  HELN.SW 26.71
3   2000-01-06  HELN.SW 27.16
4   2000-01-07  HELN.SW 27.50
5   2000-01-07  AAAA.SW 30.00
''')
df = pd.read_csv(data, sep = '\s+', index_col=0)

(我们已将 AAAA.SW 添加到列表中)

现在这个:

df.groupby('symbol')['Close'].rolling(3).mean()

产生合理的数字(因为 AAAA 只有一个日期,我们期望 NaN:


symbol    
AAAA.SW  5          NaN
HELN.SW  0          NaN
         1          NaN
         2    27.496667
         3    27.123333
         4    27.123333
Name: Close, dtype: float64

但是这个:

df.groupby('symbol')['Close'].rolling(3).mean().reset_index(drop=True)

产生错误的索引

0          NaN
1          NaN
2          NaN
3    27.496667
4    27.123333
5    27.123333
Name: Close, dtype: float64

并且当放入原始 df 时最终出现在错误的行中:

df['avg'] = df.groupby('symbol')['Close'].rolling(3).mean().reset_index(drop=True)
df

产生

     Date       symbol  Close   avg
0   2000-01-03  HELN.SW 28.28   NaN
1   2000-01-04  HELN.SW 27.50   NaN
2   2000-01-05  HELN.SW 26.71   NaN
3   2000-01-06  HELN.SW 27.16   27.496667
4   2000-01-07  HELN.SW 27.50   27.123333
5   2000-01-07  AAAA.SW 30.00   27.123333

一个解决方案是在每个组内进行分配,如下所示:

df.groupby('symbol').apply(lambda g: g.assign(avg = g['Close'].rolling(3).mean())).reset_index(drop=True)

所以我们得到


    Date        symbol  Close   avg
0   2000-01-07  AAAA.SW 30.00   NaN
1   2000-01-03  HELN.SW 28.28   NaN
2   2000-01-04  HELN.SW 27.50   NaN
3   2000-01-05  HELN.SW 26.71   27.496667
4   2000-01-06  HELN.SW 27.16   27.123333
5   2000-01-07  HELN.SW 27.50   27.123333