首页 > 解决方案 > pandas.DataFrame.cumsum 函数的问题

问题描述

我在python中有以下数据框:

month = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,1,2,3,4]
active = [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1]
data1 = [1709.1,3869.7,4230.4,4656.9,48566.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93738.2,189293.2,194412.6,206585.8]
df = pd.DataFrame({
                    'month' : month,
                    'active' : active,
                    'd1' : data1,
                    'calculate' : 0,
                });

我想通过以下方式计算“计算”列:

    月活跃 d1 计算
0 1 1 1709.1 569.70
1 2 1 3869.7 1859.60
2 3 1 4230.4 3269.73
3 4 1 4656.9 4822.03
4 5 0 48566.0 0.00
5 6 0 0.0 0.00
6 7 0 0.0 0.00
7 8 0 0.0 0.00
8 9 0 0.0 0.00
9 10 0 0.0 0.00
10 11 0 0.0 0.00
11 12 0 0.0 0.00
12 13 0 0.0 0.00
13 14 0 0.0 0.00
14 15 0 0.0 0.00
15 16 0 0.0 0.00
16 17 0 0.0 0.00
17 18 0 0.0 0.00
18 19 0 0.0 0.00
19 20 0 0.0 0.00
20 1 1 93738.2 31246.07
21 2 1 189293.2 94343.80
22 3 1 194412.6 159148.00
23 4 1 206585.8 228009.93

我正在通过以下方式进行操作:

df['calculate'] = np.where(
                        df.month > 1,
                        np.where(
                                    df.active,
                                    (df.d1/3).cumsum(),
                                    0,
                        ),
                        (df['d1']/3)
                    )

但结果不是预期的:

    月活跃 d1 计算
0 1 1 1709.1 569.700000
1 2 1 3869.7 1859.600000
2 3 1 4230.4 3269.733333
3 4 1 4656.9 4822.033333
4 5 0 48566.0 0.000000
5 6 0 0.0 0.000000
6 7 0 0.0 0.000000
7 8 0 0.0 0.000000
8 9 0 0.0 0.000000
9 10 0 0.0 0.000000
10 11 0 0.0 0.000000
11 12 0 0.0 0.000000
12 13 0 0.0 0.000000
13 14 0 0.0 0.000000
14 15 0 0.0 0.000000
15 16 0 0.0 0.000000
16 17 0 0.0 0.000000
17 18 0 0.0 0.000000
18 19 0 0.0 0.000000
19 20 0 0.0 0.00
20 1 1 93738.2 31246.07
21 2 1 189293.2 115354.50
22 3 1 194412.6 180158.70
23 4 1 206585.8 249020.63

我不知道我的要求是否清楚,我感谢谁能帮助我。

标签: pythonpython-3.xpandasnumpy

解决方案


新答案

您的条件使您的问题过于复杂,您的问题可以简化为:

df.groupby(df.active.ne(df.active.shift()).cumsum()).d1.cumsum().div(3) * df.active

0        569.700000
1       1859.600000
2       3269.733333
3       4822.033333
4          0.000000
5          0.000000
6          0.000000
7          0.000000
8          0.000000
9          0.000000
10         0.000000
11         0.000000
12         0.000000
13         0.000000
14         0.000000
15         0.000000
16         0.000000
17         0.000000
18         0.000000
19         0.000000
20     31246.066667
21     94343.800000
22    159148.000000
23    228009.933333
dtype: float64

旧答案(我认为包含解释正在尝试的逻辑仍然很有用)

您只需要 1 的连续区域的累积总和,但是,当您到达 DataFrame 的末尾时,您将继续使用 DataFrame 其余部分的累积总和。一种解决方案是cumsum计算每组连续的 1,然后在最终检查中使用此结果。


我也喜欢避免将调用链接到np.wherenp.select易于阅读的时间。

s = df.groupby(df.active.ne(df.active.shift()).cumsum()).d1.cumsum()

c1 = df.month.gt(1) & df.active
c2 = df.month.gt(1) & ~df.active

df.assign(calculate=np.select([c1, c2], [s.div(3), 0], df.d1.div(3)))

    month  active        d1      calculate
0       1       1    1709.1     569.700000
1       2       1    3869.7    1859.600000
2       3       1    4230.4    3269.733333
3       4       1    4656.9    4822.033333
4       5       0   48566.0       0.000000
5       6       0       0.0       0.000000
6       7       0       0.0       0.000000
7       8       0       0.0       0.000000
8       9       0       0.0       0.000000
9      10       0       0.0       0.000000
10     11       0       0.0       0.000000
11     12       0       0.0       0.000000
12     13       0       0.0       0.000000
13     14       0       0.0       0.000000
14     15       0       0.0       0.000000
15     16       0       0.0       0.000000
16     17       0       0.0       0.000000
17     18       0       0.0       0.000000
18     19       0       0.0       0.000000
19     20       0       0.0       0.000000
20      1       1   93738.2   31246.066667
21      2       1  189293.2   94343.800000
22      3       1  194412.6  159148.000000
23      4       1  206585.8  228009.933333

推荐阅读