如果我有每日值,如何使用Pandas计算每周累积值总和?

时间:2019-11-01 18:14:53

标签: python pandas cumsum

我是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

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

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

感谢任何提示或建议!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

如果我对您的理解正确,那么您需要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

答案 2 :(得分:0)

编辑:没有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)

是一种说法,即“获取Series 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语句之外是一种表达方式,“这是我想要加和的列”(即,不加总天数)。 如果更直观,则可以先编写它。 (这很令人高兴,也令人沮丧,熊猫不仅拥有一种而且只有一种正确的做事方式。)

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

同样,您希望适当地调整年和月,但是重新采样的好处是您可以轻松地按预定义的时间间隔(周,天,分钟等)和自定义跨度进行汇总。