Pandas:组内有两个条件的累计和
Pandas: Cumulative sum within group with two conditions
我有一个如下所示的 DataFrame table:
索引
x
y
value_1
cumsum_1
cumsum_2
0
0.1
1
12
12
0
1
1.2
1
10
12
10
2
0.25
1
7
19
10
3
1.0
2
3
0
3
4
0.72
2
5
5
10
5
1.5
2
10
5
13
所以我的目标是计算value_1
的累计和。但有两个条件必须考虑。
- 首先:如果值
x
小于 1,则 cumsum()
写入第 cumsum_1
列,如果 x
大于第 cumsum_2
列。
- 第二:第
y
列表示组 (1,2,3,...)。当 y
中的值改变时,cumsum()
-操作重新开始。我认为 grouby()
方法会有所帮助。
有人知道吗?
可以在x
< 1或x
>= 1条件下使用.where()
根据条件临时修改value_1
的值为0,然后groupby cumsum,如下:
第二个条件由 .groupby
函数满足,而第一个条件由 .where()
函数满足,详情如下:
.where()
在条件为真时保留列值,在条件为假时更改值(在本例中为 0)。因此,对于列 x
< 1 的第一个条件,value_1
将保留其值以提供给后续 cumsum
步骤以累积 value_1
的过滤值。对于条件 x
< 1 为 False 的行,value_1
将其值屏蔽为 0。这些 0 传递给 cumsum
进行累加实际上与取出原始值的效果相同value_1
为累积成
列 cumsum_1
.
第二行代码将value_1
个值累加到cumsum_2
列,条件相反x
>= 1。这两行代码实际上分配了value_1
到 cumsum_1
和 cumsum_2
分别根据 x
< 1 和 x
>= 1。
(感谢@tdy 精简代码的建议)
df['cumsum_1'] = df['value_1'].where(df['x'] < 1, 0).groupby(df['y']).cumsum()
df['cumsum_2'] = df['value_1'].where(df['x'] >= 1, 0).groupby(df['y']).cumsum()
结果:
print(df)
x y value_1 cumsum_1 cumsum_2
0 0.10 1 12 12 0
1 1.20 1 10 12 10
2 0.25 1 7 19 10
3 1.00 2 3 0 3
4 0.72 2 5 5 3
5 1.50 2 10 5 13
这是另一种使用枢轴的方法:
(df.assign(ge1=df['x'].ge(1).map({True: 'cumsum_2', False: 'cumsum_1'}))
.pivot(columns='ge1', values='value_1').fillna(0).groupby(df['y']).cumsum()
.astype(int)
)
输出:
ge1 cumsum_1 cumsum_2
0 12 0
1 12 10
2 19 10
3 0 3
4 5 3
5 5 13
完整代码:
df[['cumsum_1', 'cumsum_2']] = (df.assign(ge1=df['x'].ge(1).map({True: 'cumsum_2', False: 'cumsum_1'}))
.pivot(columns='ge1', values='value_1').fillna(0).groupby(df['y']).cumsum()
.astype(int)
)
(或用pd.concat
拼接)
输出:
index x y value_1 cumsum_1 cumsum_2
0 0 0.10 1 12 12 0
1 1 1.20 1 10 12 10
2 2 0.25 1 7 19 10
3 3 1.00 2 3 0 3
4 4 0.72 2 5 5 3
5 5 1.50 2 10 5 13
与上述方法类似,但链接更多。
df[['cumsum_1a', 'cumsum2a']] = (df.
assign(
v1 = lambda temp: temp.x >= 1,
v2 = lambda temp: temp.v1 * temp.value_1,
v3 = lambda temp: ~ temp.v1 * temp.value_1
).
groupby('y')[['v2', 'v3']].
cumsum()
)
我有一个如下所示的 DataFrame table:
索引 | x | y | value_1 | cumsum_1 | cumsum_2 |
---|---|---|---|---|---|
0 | 0.1 | 1 | 12 | 12 | 0 |
1 | 1.2 | 1 | 10 | 12 | 10 |
2 | 0.25 | 1 | 7 | 19 | 10 |
3 | 1.0 | 2 | 3 | 0 | 3 |
4 | 0.72 | 2 | 5 | 5 | 10 |
5 | 1.5 | 2 | 10 | 5 | 13 |
所以我的目标是计算value_1
的累计和。但有两个条件必须考虑。
- 首先:如果值
x
小于 1,则cumsum()
写入第cumsum_1
列,如果x
大于第cumsum_2
列。 - 第二:第
y
列表示组 (1,2,3,...)。当y
中的值改变时,cumsum()
-操作重新开始。我认为grouby()
方法会有所帮助。
有人知道吗?
可以在x
< 1或x
>= 1条件下使用.where()
根据条件临时修改value_1
的值为0,然后groupby cumsum,如下:
第二个条件由 .groupby
函数满足,而第一个条件由 .where()
函数满足,详情如下:
.where()
在条件为真时保留列值,在条件为假时更改值(在本例中为 0)。因此,对于列 x
< 1 的第一个条件,value_1
将保留其值以提供给后续 cumsum
步骤以累积 value_1
的过滤值。对于条件 x
< 1 为 False 的行,value_1
将其值屏蔽为 0。这些 0 传递给 cumsum
进行累加实际上与取出原始值的效果相同value_1
为累积成
列 cumsum_1
.
第二行代码将value_1
个值累加到cumsum_2
列,条件相反x
>= 1。这两行代码实际上分配了value_1
到 cumsum_1
和 cumsum_2
分别根据 x
< 1 和 x
>= 1。
(感谢@tdy 精简代码的建议)
df['cumsum_1'] = df['value_1'].where(df['x'] < 1, 0).groupby(df['y']).cumsum()
df['cumsum_2'] = df['value_1'].where(df['x'] >= 1, 0).groupby(df['y']).cumsum()
结果:
print(df)
x y value_1 cumsum_1 cumsum_2
0 0.10 1 12 12 0
1 1.20 1 10 12 10
2 0.25 1 7 19 10
3 1.00 2 3 0 3
4 0.72 2 5 5 3
5 1.50 2 10 5 13
这是另一种使用枢轴的方法:
(df.assign(ge1=df['x'].ge(1).map({True: 'cumsum_2', False: 'cumsum_1'}))
.pivot(columns='ge1', values='value_1').fillna(0).groupby(df['y']).cumsum()
.astype(int)
)
输出:
ge1 cumsum_1 cumsum_2
0 12 0
1 12 10
2 19 10
3 0 3
4 5 3
5 5 13
完整代码:
df[['cumsum_1', 'cumsum_2']] = (df.assign(ge1=df['x'].ge(1).map({True: 'cumsum_2', False: 'cumsum_1'}))
.pivot(columns='ge1', values='value_1').fillna(0).groupby(df['y']).cumsum()
.astype(int)
)
(或用pd.concat
拼接)
输出:
index x y value_1 cumsum_1 cumsum_2
0 0 0.10 1 12 12 0
1 1 1.20 1 10 12 10
2 2 0.25 1 7 19 10
3 3 1.00 2 3 0 3
4 4 0.72 2 5 5 3
5 5 1.50 2 10 5 13
与上述方法类似,但链接更多。
df[['cumsum_1a', 'cumsum2a']] = (df.
assign(
v1 = lambda temp: temp.x >= 1,
v2 = lambda temp: temp.v1 * temp.value_1,
v3 = lambda temp: ~ temp.v1 * temp.value_1
).
groupby('y')[['v2', 'v3']].
cumsum()
)