【问题标题】:Rolling mean of 1 year after filtering of data in pandas dataframe过滤熊猫数据框中数据后 1 年的滚动平均值
【发布时间】:2020-09-21 06:04:30
【问题描述】:

我正在尝试在下面的 pandas 数据框中计算 1 年的滚动平均值。以下数据框的“mean_1year”是使用基于 1 年计算的 按月和年。

例如,以下数据框中第一行的月份和年份是“05”和“2016”。因此“mean_1year”是使用“2016-04”的平均“价格”计算回“2015-04”。因此 将是 (1300+1400+1500)/3 = 1400。此外,在计算此平均值时,必须在“类型”列上进行过滤。由于第一行的“类型”是“A”,在计算“mean_1year”时, 必须在 type=="A" 上过滤行,并使用 '2016-04' 返回到 '2015-04' 计算平均值。

type year   month    price  mean_1year
A    2016   05       1200   1400
A    2016   04       1300
A    2016   01       1400
A    2015   12       1500

任何建议将不胜感激。谢谢!

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    首先,您需要一个按升序排列的日期时间索引,以便您可以应用滚动时间段计算。

    df['date'] = pd.to_datetime(df['year'].astype('str')+'-'+df['month'].astype('str'))
    df = df.set_index('date')
    df = df.sort_index()
    

    然后你按类型分组并应用滚动平均值。

    df['mean_1year'] = df.groupby('type')['price'].rolling('365D').mean().reset_index(0,drop=True)
    

    结果是:

               type  year  month  price  mean_1year
    date                                           
    2015-12-01    A  2015     12   1500      1500.0
    2016-01-01    A  2016      1   1400      1450.0
    2016-04-01    A  2016      4   1300      1400.0
    2016-05-01    A  2016      5   1200      1350.0
    

    【讨论】:

      【解决方案2】:

      “普通”滚动不能应用,因为它:

      • 包括从当前行开始的行,而您想要 排除它,
      • 窗口的范围扩展到未来, 而您想向后扩展

      所以我使用了不同的方法,基于 loc 日期切片。

      作为我使用的测试DataFrame:

        type  year  month  price
      0    A  2016      5   1200
      1    A  2016      4   1300
      2    A  2016      1   1400
      3    A  2015     12   1500
      4    B  2016      5   1200
      5    B  2016      4   1300
      

      代码如下:

      1. 计算 12 个月零 1 天的日期偏移量:

        yearOffs = pd.offsets.DateOffset(months=12)
        dayOffs = pd.offsets.DateOffset(days=1)
        

        稍后会在loc中用到。

      2. 将索引设置为 datetime,派生自 year列:

        df.set_index(pd.to_datetime(df.year.astype(str)
            + df.month.astype(str), format='%Y%m'), inplace=True)
        
      3. 定义计算当前均值的函数 组:

        def myMeans(grp):
            wrk = grp.sort_index()
            return wrk.apply(lambda row: wrk.loc[row.name - yearOffs
                : row.name - dayOffs, 'price'].mean(), axis=1)
        
      4. 计算均值:

        means = df.groupby('type').apply(myMeans).swaplevel()
        

        目前的结果是:

                    type
        2015-12-01  A          NaN
        2016-01-01  A       1500.0
        2016-04-01  A       1450.0
        2016-05-01  A       1400.0
        2016-04-01  B          NaN
        2016-05-01  B       1300.0
        dtype: float64
        

        df 有一个级索引,具有非唯一值。

      5. 所以将 means 添加到 df 并删除现在不必要的索引, 最后一步是:

        df = df.set_index('type', append=True).assign(mean_1year=means)\
            .reset_index(level=1).reset_index(drop=True)
        

      最终结果是:

        type  year  month  price  mean_1year
      0    A  2016      5   1200      1400.0
      1    A  2016      4   1300      1450.0
      2    A  2016      1   1400      1500.0
      3    A  2015     12   1500         NaN
      4    B  2016      5   1200      1300.0
      5    B  2016      4   1300         NaN
      

      对于每组中的“最早”行,结果为 NaN, 因为没有源(早期)行来计算均值 对他们来说(所以其他解决方案显然有问题)。

      【讨论】:

        猜你喜欢
        • 2018-11-16
        • 2018-05-15
        • 2018-08-29
        • 1970-01-01
        • 2020-01-15
        • 1970-01-01
        • 2021-03-10
        • 2020-04-26
        • 2014-02-25
        相关资源
        最近更新 更多