如何在Pandas中计算cumsum时跳过ID重复行,仅累加最后值?
实现仅保留每个ID最新行的累计和计算
需求说明
需要计算累计和,但仅将每个ID到当前行为止的最后一条记录纳入计算,忽略该ID之前的所有重复行,同时避免使用迭代循环。
示例数据
import pandas as pd import numpy as np id_list = ['a','b','c','a','b','e','f','a','b','k'] value_list = [12,14,3,13,16,7,4,6,10,18] df = pd.DataFrame({'id': id_list, 'value': value_list}) # 预期输出 df["desired_output"] = [12,26,29,30,32,39,43,36,30,48]
尝试的错误代码
df["duped"] = np.where(df["id"].duplicated(keep='last'),0,1) df["value_duped"] = df["duped"] * df["value"] df["desired_output_attempt"] = df["cumsum_of_value"] - df["value_duped"]
解决方案
核心思路是:每次遇到同一ID的新行时,用新值替换旧值的贡献,通过计算**值的变化量(delta)**并累计,得到每一行的有效总和。
# 1. 按ID分组,计算每行相对于同ID上一行的变化量(首次出现的行以上一次值为0计算) df['delta'] = df.groupby('id')['value'].transform(lambda x: x - x.shift(fill_value=0)) # 2. 累计所有变化量,得到预期结果 df['desired_output'] = df['delta'].cumsum() # 查看结果 print(df[['id', 'value', 'desired_output']])
结果验证
输出结果完全匹配预期:
id value desired_output 0 a 12 12.0 1 b 14 26.0 2 c 3 29.0 3 a 13 30.0 4 b 16 32.0 5 e 7 39.0 6 f 4 43.0 7 a 6 36.0 8 b 10 30.0 9 k 18 48.0
原理说明
- 对于每个ID的首次出现行,
delta等于自身value(因为上一次值为0),累计后相当于加入该ID的值。 - 对于同一ID的后续行,
delta等于当前value减去上一次出现的value,累计后相当于用新值替换旧值的贡献。 - 最终的累计结果就是到当前行为止所有ID最后一次出现的值的总和,完全符合需求。
内容的提问来源于stack exchange,提问作者peterW
相关产品推荐
相关产品推荐

