使用Pandas中的groupby、shift和rolling函数

3

我正在尝试在组内计算滚动平均值。为了完成这个任务,我想要从上面的行中得到滚动平均值,所以认为最简单的方法是使用shift(),然后执行 rolling()。问题是shift()会将前一个组的数据移动,使组2和3中的第一行不正确。列 'ma' 应该在第4行和第7行具有 NaN。我该如何解决这个问题?

import pandas as pd

df = pd.DataFrame(
    {"Group": [1, 2, 3, 1, 2, 3, 1, 2, 3],
     "Value": [2.5, 2.9, 1.6, 9.1, 5.7, 8.2, 4.9, 3.1, 7.5]
     })

df = df.sort_values(['Group'])
df.reset_index(inplace=True)

df['ma'] = df.groupby('Group', as_index=False)['Value'].shift(1).rolling(3, min_periods=1).mean()

print(df)

我得到了这个:

   index  Group  Value    ma
0      0      1    2.5   NaN
1      3      1    9.1  2.50
2      6      1    4.9  5.80
3      1      2    2.9  5.80
4      4      2    5.7  6.00
5      7      2    3.1  4.30
6      2      3    1.6  4.30
7      5      3    8.2  3.65
8      8      3    7.5  4.90

我尝试过几个类似问题的答案,但似乎都不起作用。


您的最小期限为1。您怎么可能有NaN? - Balaji Ambresh
由于shift函数的原因,第一行没有前一行。因此,它基本上有0个先前期间,导致NaN。 - SoSincere3
@SoSincere3,非常感谢您的解释。不确定我是否已经发布了回复。也许是有人黑进了我的账户。无论如何还是感谢您。 - Balaji Ambresh
1个回答

2

如果我理解问题正确,那么你需要的解决方案可以通过以下2个步骤实现:

df['sa'] = df.groupby('Group', as_index=False)['Value'].transform(lambda x: x.shift(1))

df['ma'] = df.groupby('Group', as_index=False)['sa'].transform(lambda x: x.rolling(3, min_periods=1).mean())

我得到了下面的输出,其中“ma”是所需的列。
index   Group   Value   sa  ma
0   0   1   2.5     NaN     NaN
1   3   1   9.1     2.5     2.5
2   6   1   4.9     9.1     5.8
3   1   2   2.9     NaN     NaN
4   4   2   5.7     2.9     2.9
5   7   2   3.1     5.7     4.3
6   2   3   1.6     NaN     NaN
7   5   3   8.2     1.6     1.6
8   8   3   7.5     8.2     4.9

编辑:一个分组的示例

def shift_ma(x):
    return x.shift(1).rolling(3, min_periods=1).mean()

df['ma'] = df.groupby('Group', as_index=False)['Value'].apply(shift_ma).reset_index(drop=True)

这正是我所需要的!为什么不可以在一步中不使用 transform() 就能运行? - Mudyla
1
当您执行'shift(1)'时,您正在关闭分组部分。现在,当您调用'rolling'时,它将在非分组数据帧上工作。因此,您的滚动跨越了组,因为在调用'shift'时组已丢失。基本上,您需要两个单独的'groupby',一个用于'shift',另一个用于滚动平均值。在这种情况下,变换没有特殊价值。您可以尝试使用2个'groupby'和简单的'shift',然后是'rolling mean'。每当新列的长度必须与父列相同时,我都会使用transform。习惯力量 :) - Yati Raj
没有使用两个“groupby”的理由。一个带有“apply”的“groupby”应该足以解决这个问题。 - Andy L.
2
是的,安迪。那也可以。我只是遵循了一种思路。感谢提供另一种选择。 - Yati Raj
你可以加一个使用 groupbyapply 的示例吗?谢谢! - Mudyla

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