如何按id列分组计算cost总和,忽略omit=True的组最后一行
问题描述
现有一个包含3列的DataFrame:
id:整数类型,相同id的行已连续排列cost:浮点类型omit:布尔类型,多数行值为False,部分id的最后一行值为True
需求是新增total_cost列,计算每个id对应的cost总和,但需要忽略该id组中最后一行且omit=True的记录。
已完成分组求和的代码:
df["total_cost"] = df.groupby("id")["cost"].transform("sum")
但不确定如何以向量化方式实现「若组最后一行omit=True则减去该行cost」的逻辑。
示例输入输出如下:
id cost omit total_cost 0 1.1 False 2.1 0 1.0 False 2.1 0 2.2 True 2.1 1 3.2 False 3.2 1 4.0 True 3.2 2 0.5 False 1.2 2 0.4 False 1.2 2 0.3 False 1.2
解决方案
你的思路完全正确——先计算全量分组总和,再对符合条件的组扣除对应值,这种方式比过滤后再求和更高效,尤其是数据量大的时候。可以通过以下向量化步骤实现:
标记每个组的最后一行:
用groupby('id').cumcount(ascending=False)可以得到每个组内从后往前的序号,序号为0的就是该组最后一行。提取需要扣除的
cost值:
筛选出「是组最后一行且omit=True」的记录,提取对应的id和cost,做成一个以id为索引的Series。对分组总和做扣除修正:
用transform把上述扣除值映射到每个组,没有需要扣除的组则用0填充,最后从原总和中减去该值。
完整代码如下:
import pandas as pd # 示例数据 df = pd.DataFrame({ 'id': [0,0,0,1,1,2,2,2], 'cost': [1.1,1.0,2.2,3.2,4.0,0.5,0.4,0.3], 'omit': [False, False, True, False, True, False, False, False] }) # 1. 计算分组总和 df['total_cost'] = df.groupby('id')['cost'].transform('sum') # 2. 标记组最后一行,并筛选出需要扣除的记录 is_last_row = df.groupby('id').cumcount(ascending=False) == 0 deduct_series = df.loc[is_last_row & df['omit'], ['id', 'cost']].set_index('id')['cost'] # 3. 对每个组应用扣除值,无扣除则减0 df['total_cost'] -= df['id'].map(deduct_series).fillna(0)
运行后得到的total_cost列完全符合示例要求。这种方式全程用Pandas的向量化操作,避免了循环,效率很高。
内容的提问来源于stack exchange,提问作者h8n2
相关产品推荐
相关产品推荐

