【问题标题】:Pandas rolling sum, variating lengthPandas 滚动总和,可变长度
【发布时间】:2015-03-10 09:54:40
【问题描述】:

我将尝试解释我目前遇到的关于 Python 中 DataFrames 的累积和的问题,希望你能掌握它!

给定一个带有 returns 列的 pandas DataFrame df

              returns
Date                                                          
2014-12-10    0.0000
2014-12-11    0.0200
2014-12-12    0.0500
2014-12-15    -0.0200
2014-12-16    0.0000

在此 DataFrame 上应用累积和很容易,只需使用例如df.cumsum()。但是是否可以每隔X 天(或数据点)应用一个累积总和,例如,只产生最后一个 Y 天(数据点)的累积总和。

澄清:给定上述每日数据,我如何获得最后Y 天的累计总和,每X 天重新评估一次(从零开始)?

希望它足够清楚,

谢谢, 否

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我不确定是否有内置方法,但编写一个似乎并不难。 例如,这是熊猫系列的一个。

    def cum(df, interval):
        all = []
        quotient = len(df)//interval
        intervals = range(quotient)
        for i in intervals:
            all.append(df[0:(i+1)*interval].sum())
        return pd.Series(all)
    >>>s1 = pd.Series(range(20))
    >>>print(cum(s1, 4))
    0     6
    1    28
    2    66
    3   120
    4   190
    dtype: int64
    

    【讨论】:

    • 我想你误解了这个问题
    • 现在我担心我没有正确理解它。按照我的理解,用你的数字和y 2,cumsum 将是 [0,0,2,5,0,0,6,13,0,0,10,21,.. .],一个 cumsum 重置每个 x 数据点,但也不考虑第一个 x-y 数据点。
    【解决方案2】:

    我会这样做的方式是使用辅助列。这有点笨拙,但应该可以:

    numgroups = int(len(df)/(x-1))
    df['groupby'] = sorted(list(range(numgroups))*x)[:len(df)]
    df['mask'] = (([0]*(x-y)+[1]*(y))*numgroups)[:len(df)]
    df['masked'] = df.returns*df['mask']
    df.groupby('groupby').masked.cumsum()
    

    【讨论】:

      【解决方案3】:

      “每 X 天”和“每 X 数据点”有很大不同;以下假设您真正的意思是第一个,因为您更频繁地提及它。

      如果索引是DatetimeIndex,你可以resample到一个日频,取一个rolling_sum,然后只选择原来的日期:

      >>> pd.rolling_sum(df.resample("1d"), 2, min_periods=1).loc[df.index]
                  returns
      Date               
      2014-12-10     0.00
      2014-12-11     0.02
      2014-12-12     0.07
      2014-12-15    -0.02
      2014-12-16    -0.02
      

      或者,一步一步:

      >>> df.resample("1d")
                  returns
      Date               
      2014-12-10     0.00
      2014-12-11     0.02
      2014-12-12     0.05
      2014-12-13      NaN
      2014-12-14      NaN
      2014-12-15    -0.02
      2014-12-16     0.00
      >>> pd.rolling_sum(df.resample("1d"), 2, min_periods=1)
                  returns
      Date               
      2014-12-10     0.00
      2014-12-11     0.02
      2014-12-12     0.07
      2014-12-13     0.05
      2014-12-14      NaN
      2014-12-15    -0.02
      2014-12-16    -0.02
      

      【讨论】:

        【解决方案4】:

        感谢@DSM,我设法想出了他的解决方案的变体,实际上几乎可以满足我的要求:

        import numpy as np
        import pandas as pd
        
        df.resample("1w"), how={'A': np.sum})
        

        为下面的示例提供我想要的结果:

        rng = range(1,29)
        dates = pd.date_range('1/1/2000', periods=len(rng))
        r = pd.DataFrame(rng, index=dates, columns=['A'])
        r2 = r.resample("1w", how={'A': np.sum})
        

        输出:

        >> print r
                     A
        2000-01-01   1
        2000-01-02   2
        2000-01-03   3
        2000-01-04   4
        2000-01-05   5
        2000-01-06   6
        2000-01-07   7
        2000-01-08   8
        2000-01-09   9
        2000-01-10  10
        2000-01-11  11
        ...
        2000-01-25  25
        2000-01-26  26
        2000-01-27  27
        2000-01-28  28
        
        >> print r2
                      A
        2000-01-02    3
        2000-01-09   42
        2000-01-16   91
        2000-01-23  140
        2000-01-30  130
        

        即使在这种情况下它不是从“一周”开始(在第一种情况下导致总和为 3),它总是得到正确的滚动总和,从前一个日期开始,初始值为零.

        【讨论】:

          猜你喜欢
          • 2020-12-25
          • 1970-01-01
          • 1970-01-01
          • 2018-08-16
          • 1970-01-01
          • 1970-01-01
          • 2014-08-11
          • 2019-03-15
          • 2015-03-28
          相关资源
          最近更新 更多