【问题标题】:Using shift and rolling in pandas with groupBy通过 groupBy 在 pandas 中使用 shift 和 rolling
【发布时间】:2018-08-04 15:35:49
【问题描述】:
df = pd.DataFrame(dict(
    list(
        zip(["A", "B", "C"],
            [np.array(["id %02d" % i for i in range(1, 11)]).repeat(10),
            pd.date_range("2018-01-01", periods=100).strftime("%Y-%m-%d"),
            [i for i in range(10, 110)]])
        )
))

df = df.groupby(["A", "B"]).sum()

df["D"] = df["C"].shift(1).rolling(2).mean()

df

此代码生成以下内容:

我希望为每个新 ID 重新开始滚动逻辑。现在,ID 02 正在使用来自ID 01 的最后两个值来计算平均值。

如何做到这一点?

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    相信你需要groupby:

    df['D'] = df["C"].shift(1).groupby(df['A'], group_keys=False).rolling(2).mean()
    print (df.head(20))
                       C     D
    A     B                   
    id 01 2018-01-01  10   NaN
          2018-01-02  11   NaN
          2018-01-03  12  10.5
          2018-01-04  13  11.5
          2018-01-05  14  12.5
          2018-01-06  15  13.5
          2018-01-07  16  14.5
          2018-01-08  17  15.5
          2018-01-09  18  16.5
          2018-01-10  19  17.5
    id 02 2018-01-11  20   NaN
          2018-01-12  21  19.5
          2018-01-13  22  20.5
          2018-01-14  23  21.5
          2018-01-15  24  22.5
          2018-01-16  25  23.5
          2018-01-17  26  24.5
          2018-01-18  27  25.5
          2018-01-19  28  26.5
          2018-01-20  29  27.5
    

    或者:

    df['D'] = df["C"].groupby(df['A']).shift(1).rolling(2).mean()
    print (df.head(20))
                       C     D
    A     B                   
    id 01 2018-01-01  10   NaN
          2018-01-02  11   NaN
          2018-01-03  12  10.5
          2018-01-04  13  11.5
          2018-01-05  14  12.5
          2018-01-06  15  13.5
          2018-01-07  16  14.5
          2018-01-08  17  15.5
          2018-01-09  18  16.5
          2018-01-10  19  17.5
    id 02 2018-01-11  20   NaN
          2018-01-12  21   NaN
          2018-01-13  22  20.5
          2018-01-14  23  21.5
          2018-01-15  24  22.5
          2018-01-16  25  23.5
          2018-01-17  26  24.5
          2018-01-18  27  25.5
          2018-01-19  28  26.5
          2018-01-20  29  27.5
    

    【讨论】:

    • 我现在在没有group_keys=False 参数的情况下进行了测试,它仍然有效。我真的需要这个吗?
    • 我添加它是因为在第一个解决方案中得到NaNs,但如果工作良好,可以免费省略它。
    • @Nilzone- 测试了第二种解决方案,对我来说,如果省略它会很好。
    • 是的 - 看起来至少在这种情况下它不会影响结果:)
    • @jezrael 我发现您的解决方案不适用于负值班次方法(至少部分如此)。在最初的问题中,周期是积极的,但对于全貌,我觉得应该添加负周期的正确选项。请看我的回答
    【解决方案2】:

    虽然@jezrael 接受的答案对于正偏移有效,但对于负偏移给出了不正确的结果(部分)。请检查以下内容

    df['D'] = df["C"].groupby(df['A']).shift(1).rolling(2).mean()
    df['E'] = df["C"].groupby(df['A']).rolling(2).mean().shift(1).values
    df['F'] = df["C"].groupby(df['A']).shift(-1).rolling(2).mean()
    df['G'] = df["C"].groupby(df['A']).rolling(2).mean().shift(-1).values
    df.set_index(['A', 'B'], inplace=True)
    print(df.head(20))
    
                       C     D     E     F     G
    A     B                                     
    id 01 2018-01-01  10   NaN   NaN   NaN  10.5
          2018-01-02  11   NaN   NaN  11.5  11.5
          2018-01-03  12  10.5  10.5  12.5  12.5
          2018-01-04  13  11.5  11.5  13.5  13.5
          2018-01-05  14  12.5  12.5  14.5  14.5
          2018-01-06  15  13.5  13.5  15.5  15.5
          2018-01-07  16  14.5  14.5  16.5  16.5
          2018-01-08  17  15.5  15.5  17.5  17.5
          2018-01-09  18  16.5  16.5  18.5  18.5
          2018-01-10  19  17.5  17.5   NaN   NaN
    id 02 2018-01-11  20   NaN  18.5   NaN  20.5
          2018-01-12  21   NaN   NaN  21.5  21.5
          2018-01-13  22  20.5  20.5  22.5  22.5
          2018-01-14  23  21.5  21.5  23.5  23.5
          2018-01-15  24  22.5  22.5  24.5  24.5
          2018-01-16  25  23.5  23.5  25.5  25.5
          2018-01-17  26  24.5  24.5  26.5  26.5
          2018-01-18  27  25.5  25.5  27.5  27.5
          2018-01-19  28  26.5  26.5  28.5  28.5
          2018-01-20  29  27.5  27.5   NaN   NaN
    

    请注意,DE 列是针对 .shift(1) 计算的,FG 列是针对 .shift(-1) 计算的。列E 不正确,因为id 02 的第一个值使用id 01 的最后两个值。 F 列不正确,因为 id 01id 02 的第一个值都是 NaNs。 DG 列给出了正确的结果。所以,完整的答案应该是这样的。如果班次周期为非负数,请使用以下

    df['D'] = df["C"].groupby(df['A']).shift(1).rolling(2).mean()
    

    如果 shift period 为负数,请使用以下

    df['G'] = df["C"].groupby(df['A']).rolling(2).mean().shift(-1).values
    

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2020-09-25
      • 2019-06-18
      • 2017-08-25
      • 2021-05-18
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      相关资源
      最近更新 更多