基于多列分组的 Pandas 滚动平均值

5

我有一个长格式的数据框,其中两列存在重复值,而另一列包含数据。我想找到每个分组的简单移动平均线(SMA)。我的问题是:rolling()函数无法考虑到数据按两列分组的情况。

这里是一些虚拟数据和代码:

import numpy as np
import pandas as pd

dtix=pd.Series(pd.date_range(start='1/1/2019', periods=4) )
df=pd.DataFrame({'ix1':np.repeat([0,1],4), 'ix2':pd.concat([dtix,dtix]), 'data':np.arange(0,8) })
df

当我对这些数据进行分组滚动平均时,得到的输出如下所示:
ix1 ix2 data   rolling_mean
0   0   2019-01-01  NaN
1   0   2019-01-02  NaN
2   0   2019-01-03  1.0
3   0   2019-01-04  2.0
0   1   2019-01-01  NaN
1   1   2019-01-02  NaN
2   1   2019-01-03  5.0
3   1   2019-01-04  6.0
df.groupby(['ix1','ix2']).agg({'data':'mean'}).rolling(2).mean()
数据
ix1 ix2 
0   2019年01月01日  NaN
    2019年01月02日  0.5
    2019年01月03日  1.5
    2019年01月04日  2.5
1   2019年01月01日  3.5
    2019年01月02日  4.5
    2019年01月03日  5.5
    2019年01月04日  6.5

期望输出: 然而,我实际希望得到的是这样的:

sma
ix1 ix2 
0   2019年01月01日  NaN
    2019年01月02日  0.5
    2019年01月03日  1.5
    2019年01月04日  2.5
1   2019年01月01日  NaN
    2019年01月02日  4.5
    2019年01月03日  5.5
    2019年01月04日  6.5

非常感谢您的帮助。


这是你的问题吗?https://dev59.com/66Xja4cB1Zd3GeqPQF6V - PV8
你没有在组上执行滚动均值,因为你已经对它们应用了聚合函数。 - yatu
1个回答

3

使用基于第一层(ix1)的另一个 groupby ,并结合 rolling 使用:

df1 = (df.groupby(['ix1','ix2'])
         .agg({'data':'mean'})
         .groupby(level=0, group_keys=False)
         .rolling(2)
         .mean())
print (df1)
                data
ix1 ix2             
0   2019-01-01   NaN
    2019-01-02   0.5
    2019-01-03   1.5
    2019-01-04   2.5
1   2019-01-01   NaN
    2019-01-02   4.5
    2019-01-03   5.5
    2019-01-04   6.5

在你的解决方案中,聚合后返回了一个列为DataFrame的结果,因此链式调用rolling将作用于所有行,而不是每个组,这并不符合需求。
print(df.groupby(['ix1','ix2']).agg({'data':'mean'}))
                data
ix1 ix2             
0   2019-01-01     0
    2019-01-02     1
    2019-01-03     2
    2019-01-04     3
1   2019-01-01     4
    2019-01-02     5
    2019-01-03     6
    2019-01-04     7

1
非常感谢@jezreal和@yatu。所以我的唯一groupby将两列转换为索引,剩下的单列数据框除非我再次按ix1索引分组,否则无法产生我想要的结果?这意味着我可以简单地通过df.set_index(("ix2"), inplace=False).groupby("ix1")["data"].rolling(2).mean()来完成,对吗?(好的,我已经检查过它可以工作,但不知何故我期望一个简单的多列groupby应该就能解决问题。猜想我需要思考一下groupby的工作原理)。再次感谢。 - R.S.
@R.S. - 是的,你说得对 - 还可以通过 df.set_index("ix2").groupby("ix1")["data"].rolling(2).mean() 来简化。 - jezrael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接