【问题标题】:Is there a way to do a weight-average rolling sum over a grouping?有没有办法对分组进行加权平均滚动求和?
【发布时间】:2014-05-27 20:46:41
【问题描述】:

我想对 DataFrame 应用加权和。过去我用过

for sec_id, sec_df_unidx in grouped:
    if sec_df_unidx.shape[0] > 3:
        pd.rolling_sum(sec_df[added_cols], 4)

我想对最近乘以 0.6、第二乘以 0.2、第三和第四乘以 0.1 的总和应用加权平均值。

DF:

DATE    ID  VALUE
2012-12-31  A   100
2013-03-31  A   120
2013-06-30  A   140
2013-09-30  A   160
2013-12-31  A   180
2013-03-31  B   0
2013-06-30  B   5
2013-09-30  B   1
2013-12-31  B   3
2012-12-31  C   45
2013-03-31  C   46
2013-06-30  C   42
2013-09-30  C   30
2013-12-31  C   11
2012-12-31  D   18
2013-03-31  D   9
2013-06-30  D   13
2013-09-30  D   5
2013-12-31  D   11
2012-12-31  E   0

带有新列的 DF:

DATE    ID  VALUE   Weight_Sum
2012-12-31  A   100 NaN
2013-03-31  A   120 NaN
2013-06-30  A   140 NaN
2013-09-30  A   160 146
2013-12-31  A   180 166
2013-03-31  B   0   NaN
2013-06-30  B   5   NaN
2013-09-30  B   1   NaN
2013-12-31  B   3   2.5
2012-12-31  C   45  NaN
2013-03-31  C   46  NaN
2013-06-30  C   42  NaN
2013-09-30  C   30  35.5
2013-12-31  C   11  21.4
2012-12-31  D   18  NaN
2013-03-31  D   9   NaN
2013-06-30  D   13  NaN
2013-09-30  D   5   8.3
2013-12-31  D   11  9.8
2012-12-31  E   0   NaN

我可以使用 rolling_apply 或 rolling_sum 来做到这一点吗?还是我必须做一个 for 循环?

谢谢。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我认为您可以在由普通groupby/apply 调用的函数中使用rolling_apply。所以类似于以下内容:

    def roll_wsum(g,w,p):
        rsum = pd.rolling_apply(g.values,p,lambda x: np.dot(w,x),min_periods=p)
        return pd.Series(rsum,index=g.index)
    
    weights = np.array([0.1,0.1,0.2,0.6])
    df['wsum'] = df.groupby('ID')['VALUE'].apply(roll_wsum,weights,4)
    print df
    

    输出:

             DATE ID  VALUE   wsum
    0  2012-12-31  A    100    NaN
    1  2013-03-31  A    120    NaN
    2  2013-06-30  A    140    NaN
    3  2013-09-30  A    160  146.0
    4  2013-12-31  A    180  166.0
    5  2013-03-31  B      0    NaN
    6  2013-06-30  B      5    NaN
    7  2013-09-30  B      1    NaN
    8  2013-12-31  B      3    2.5
    9  2012-12-31  C     45    NaN
    10 2013-03-31  C     46    NaN
    11 2013-06-30  C     42    NaN
    12 2013-09-30  C     30   35.5
    13 2013-12-31  C     11   21.4
    14 2012-12-31  D     18    NaN
    15 2013-03-31  D      9    NaN
    16 2013-06-30  D     13    NaN
    17 2013-09-30  D      5    8.3
    18 2013-12-31  D     11    9.8
    19 2012-12-31  E      0    NaN
    

    因此,我只是按“ID”对数据进行分组,然后将组的“VALUE”列发送到我的 roll_wsum 函数(连同加权总和和周期的权重)。 roll_wsum 函数调用 rolling_apply 并将一个简单的 lambda 函数提供给 rolling_apply:“VALUE”和权重的点积。此外,在这里施加 min_periods=4 条件也很重要,因为我们需要数组的长度(权重和 df['VALUE'].values)相同。

    鉴于我使用点积来计算加权和,它可能无法按照您想要的方式处理缺失值。因此,例如,您可能更喜欢以下内容(尽管它对示例数据没有影响):

    def roll_wsum(g,w,p):
        rsum = pd.rolling_apply(g.values,p,lambda x: np.nansum(w*x),min_periods=p)
        return pd.Series(rsum,index=g.index)
    
    weights = np.array([0.1,0.1,0.2,0.6])
    df['wsum'] = df.groupby('ID')['VALUE'].apply(roll_wsum,weights,4)
    

    【讨论】:

      猜你喜欢
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 2011-02-26
      • 2018-04-26
      相关资源
      最近更新 更多