【问题标题】:How to calculate cumulative weekly sum of values if I have daily values, using Pandas?如果我有每日值,如何使用 Pandas 计算累积的每周值总和?
【发布时间】:2019-11-01 18:14:53
【问题描述】:

我是 Pandas 的新手。我有一个看起来像这样的数据框:

days rainfall
1    3.51
2    1.32
3    0
4    0
5    0
6    0
7    0
8    0
9    0.03
10   0
11   0
12   0.17
13   0.23
14   0.02
15   0
16   0
17   0
18   0.03
19   0.02
20   0
21   0

我想添加一个列(我们称之为“累积”),它显示每周的累积降雨量值。换句话说,我想计算前 7 天 (1-7) 的累积值,然后是第二组 7 天 (8-14) 的累积值,依此类推。

最终产品如下所示:

days rainfall cumulative
1    3.51     4.83
2    1.32     0.45
3    0        0.05
4    0
5    0
6    0
7    0
8    0
9    0.03
10   0
11   0
12   0.17
13   0.23
14   0.02
15   0
16   0
17   0
18   0.03
19   0.02
20   0
21   0

到目前为止,我已经尝试用sum 调用rolling,但我没有得到我想要的。

df['cumulative']=df['rainfall'].rolling(min_periods=7, window=7).sum()

感谢任何提示或建议!

【问题讨论】:

    标签: python pandas cumsum


    【解决方案1】:

    你可以这样做:

    import pandas as pd
    
    df = pd.DataFrame([
        [ 1, 3.51],
        [ 2, 1.32],
        [ 3, 0],
        [ 4, 0],
        [ 5, 0],
        [ 6, 0],
        [ 7, 0],
        [ 8, 0],
        [9, 0.03],
        [10, 0],
        [11, 0],
        [12, 0.17],
        [13, 0.23],
        [14, 0.02],
        [15, 0],
        [16, 0],
        [17, 0],
        [18, 0.03],
        [19, 0.02],
        [20, 0],
        [21, 0]], columns=['days', 'rainfall'])
    result = df['rainfall'].groupby((df['days'] - 1) // 7).sum().reset_index(drop=True)
    print(result)
    # In [418]: %paste -q
    # 0    4.83
    # 1    0.45
    # 2    0.05
    # Name: rainfall, dtype: float64
    

    【讨论】:

      【解决方案2】:

      如果我理解正确,你想要GroupBy.transform

      # create groups of each 7 days with floordivision
      grps = df['days'].sub(1).floordiv(7)
      
      # get the cumulative sum per group
      df['cumsum'] = df.groupby(grps)['rainfall'].transform('sum')
      
          days  rainfall  cumsum
      0      1      3.51    4.83
      1      2      1.32    4.83
      2      3      0.00    4.83
      3      4      0.00    4.83
      4      5      0.00    4.83
      5      6      0.00    4.83
      6      7      0.00    4.83
      7      8      0.00    0.45
      8      9      0.03    0.45
      9     10      0.00    0.45
      10    11      0.00    0.45
      11    12      0.17    0.45
      12    13      0.23    0.45
      13    14      0.02    0.45
      14    15      0.00    0.05
      15    16      0.00    0.05
      16    17      0.00    0.05
      17    18      0.03    0.05
      18    19      0.02    0.05
      19    20      0.00    0.05
      20    21      0.00    0.05
      

      【讨论】:

      • 我只对获取每周的累计金额感兴趣。所以在这种情况下,cumsum 列实际上应该显示三个值:4.83、0.45、0.05。
      • 那不是累积总和,它只是每组的总和@PKKR_26
      • @Erfan,谢谢 - 我应该使用正确的术语。
      • 我误解了您的问题,请参阅我编辑的答案。我想这就是你想要的@PKKR_26
      【解决方案3】:

      编辑:另一种不使用 DateTime 索引的方法是 pd.cut()。

          df.groupby(pd.cut(df.days, bins=3, 
              precision=0))["rainfall"].sum()
      
          days
          (1.0, 8.0]      4.83
          (8.0, 14.0]     0.45
          (14.0, 21.0]    0.05
      

      cut 方法允许您指定一个频率范围来分箱值。

          pd.cut(df.days, bins=3)
      

      是一种表示“将系列 df["days"] 并将其分成三个块”的方式。如果您单独运行该代码,您会看到:

          0       (1.0, 8.0]
          1       (1.0, 8.0]
          2       (1.0, 8.0]
          .
          .
          .
          19    (14.0, 21.0]
          20    (14.0, 21.0]
      

      它用它所属的 bin 标记 DataFrame 中的每一行。然后您可以将其用作 groupby 语句中的参数,就像任何其他列属性一样,并应用聚合函数。

      将 ["rainfall"] 放在 groupby 语句之外是一种说法,“这是我想要总和的列”(即,不要对天数求和)。 如果这样更直观,您可以先交替编写它。 (这很棒,但也令人沮丧,pandas 有不止一种,而且只有一种正确的做事方式。)

      df["rainfall"].groupby(...)
      

      原始答案:

      对于聚合统计,您可以使用 pd.resample()。这是一个 DateTime 索引方法(我不得不在这里稍微强制一下,但通常你会有更多关于天气时间戳的内容)。

          df.resample("W").sum()["rainfall"]
      

      是将天数缩减为数周并汇总值的代码。

      在这种情况下,我从字典构造了一个 DataFrame,并将索引转换为 DateTime 格式以使用 resample 方法:

          df = pd.DataFrame( 
              data={
                  "days": (list(range(1,22))), 
                  "rainfall": [3.51,
                      1.32, 0, 0, 0, 0, 0, 0, 0.03, 
                      0, 0, 0.17, 0.23, 0.02, 0, 0,  
                      0, 0.03, 0.02, 0, 0]}, 
                   index=pd.to_datetime(list(range(1,22)), format="%d",
                   errors="coerce"))
      

      这让你:

          1900-01-07    4.83
          1900-01-14    0.45
          1900-01-21    0.05
          Freq: W-SUN, Name: rainfall, dtype: float64
      

      同样,您希望根据需要调整年份和月份,但重新采样的好处是您可以轻松地按预定义的时间间隔(周、天、分钟等)和自定义跨度进行聚合。

      【讨论】:

      • 谢谢 - 这是一个很好的答案,实际上也仅每 7 天显示一次,并简化了我的下一步分析!
      • 很高兴为您提供帮助!您还可以告诉 pandas 从一周中的哪一天开始(星期日与星期一),间隔的哪一侧关闭,等等。这是 resample 的文档字符串,老实说,它作为参考非常有用:ithhttps://github .com/pandas-dev/pandas/blob/master/pandas/core/generic.py#L8135-L8453
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-13
      • 2021-06-07
      • 2019-03-05
      • 1970-01-01
      • 2022-06-18
      相关资源
      最近更新 更多