Pandas 日期移动平均线

Pandas Moving Average on Date

我有一个 df 如下所示:

为数据框添加代码:

df = pd.DataFrame({'Name':['John']*12
                  ,'Type':[*'AABBBBAAABAB']
                  ,'Period':['Noon','Morning']*6
                  ,'Date':['1/1/2020']*2+['1/4/2020']*2+
                          ['1/5/2020']*2+['1/2/2020']*2+
                          ['1/3/2020']*2+['1/19/2020', '1/31/2020']
                  ,'value':[1,2,7,8,9,10,3,4,5,6,5,6]}, index=range(1,13))

基本上我需要一个人(以 John 为例)价值的连续 2 天移动平均线,按类型和时期分类(人也是,但不在此 table 中)。

预期结果如最后一栏所示。 例如1。第 4 行,John 早上的 B 型,2020 年 1 月 4 日和 2020 年 1 月 3 日(第 10 行)的平均值为 (6+8)/2=7, 并且没有 2020 年 1 月 3 日之前的 John 类型 B 的数据,因此第 10 行结果为 na

例如2。第 11 行和第 12 行,它们不是连续的日期,所以都是 na

如何使用pandas实现这个功能?我应该使用 transform 还是 rolling

您可以使用以下内容:

df.set_index('Date')\
  .groupby(['Name','Type','Period'])['value']\
  .rolling('2D', min_periods=2)\
  .mean()\
  .reset_index()

输出:

    Name Type   Period       Date  value
0   John    A  Morning 2020-01-01    NaN
1   John    A  Morning 2020-01-02    3.0
2   John    A     Noon 2020-01-01    NaN
3   John    A     Noon 2020-01-02    2.0
4   John    A     Noon 2020-01-03    4.0
5   John    A     Noon 2020-01-19    NaN
6   John    B  Morning 2020-01-04    NaN
7   John    B  Morning 2020-01-05    9.0
8   John    B  Morning 2020-01-03    8.0
9   John    B  Morning 2020-01-31    NaN
10  John    B     Noon 2020-01-04    NaN
11  John    B     Noon 2020-01-05    8.0

并且,一种将其合并回原始数据框的方法:

df_er = (df.set_index('Date')
           .groupby(['Name','Type','Period'])['value']
           .rolling('2D', min_periods=2)
           .mean()
           .rename('Expected Result'))
df.merge(df_er, left_on=['Name', 'Type', 'Period', 'Date'], right_index=True)

输出:

    Name Type   Period       Date  value  Expected Result
1   John    A     Noon 2020-01-01      1              NaN
2   John    A  Morning 2020-01-01      2              NaN
3   John    B     Noon 2020-01-04      7              NaN
4   John    B  Morning 2020-01-04      8              NaN
5   John    B     Noon 2020-01-05      9              8.0
6   John    B  Morning 2020-01-05     10              9.0
7   John    A     Noon 2020-01-02      3              2.0
8   John    A  Morning 2020-01-02      4              3.0
9   John    A     Noon 2020-01-03      5              4.0
10  John    B  Morning 2020-01-03      6              8.0
11  John    A     Noon 2020-01-19      5              NaN
12  John    B  Morning 2020-01-31      6              NaN