如何用GroupBy实现按ID分组后求和最后del事件后的数值?
批量计算分组后最后一个del事件的后续Number总和
需求说明
针对包含多id的表格数据,需先按id和datetime排序,再对每个id分组,计算该组最后一次del事件发生后所有行的Number列之和。已有单个id的处理代码,现需通过GroupBy实现批量处理。
示例数据结构
| Event | Number | datetime | id |
|---|---|---|---|
| add | 10 | 1/1/22 | 1 |
| del | 0 | 1/2/22 | 1 |
| add | 12 | 1/4/22 | 1 |
| del | 0 | 1/5/22 | 1 |
| add | 12 | 1/6/22 | 1 |
| add | 2 | 1/15/22 | 1 |
| sub | -6 | 1/16/22 | 1 |
| add | 10 | 1/1/22 | 2 |
| del | 0 | 1/2/22 | 2 |
| add | 12 | 1/4/22 | 2 |
| del | 0 | 1/5/22 | 2 |
| add | 12 | 1/6/22 | 2 |
| add | 2 | 1/15/22 | 2 |
| sub | -6 | 1/16/22 | 2 |
实现方案
步骤1:预处理数据(转换时间格式+排序)
首先确保datetime列为时间类型,避免字符串排序错误,再按id和datetime排序:
import pandas as pd # 转换datetime列为时间类型 df['datetime'] = pd.to_datetime(df['datetime']) # 按id和datetime排序 df = df.sort_values(['id', 'datetime'])
步骤2:GroupBy批量处理(方法一:apply自定义函数)
通过groupby('id').apply()对每个分组执行逻辑,适合逻辑复杂的场景:
def calc_sum_after_last_del(group): # 获取当前分组最后一个del事件的时间 del_rows = group[group['Event'] == 'del'] if not del_rows.empty: last_del_dt = del_rows['datetime'].iloc[-1] else: # 无del事件时,可根据需求返回0或全量求和,这里返回0 return 0 # 筛选最后del之后的行,求和Number return group[group['datetime'] > last_del_dt]['Number'].sum() # 应用到所有id分组 result = df.groupby('id').apply(calc_sum_after_last_del)
执行后result会输出每个id对应的结果:
id 1 8 2 8 dtype: int64
步骤3:更高效的实现(方法二:transform标记筛选)
针对大数据量场景,用transform给每行标记所属id的最后del时间,再直接筛选求和,性能更优:
# 为每行添加所属id的最后del时间 df['last_del_dt'] = df.groupby('id').apply( lambda x: x[x['Event'] == 'del']['datetime'].iloc[-1] if not x[x['Event'] == 'del'].empty else pd.Timestamp.min ).reset_index(level=0, drop=True) # 筛选最后del之后的行,分组求和 result = df[df['datetime'] > df['last_del_dt']].groupby('id')['Number'].sum()
关键说明
- 若分组中无
del事件,可根据需求调整逻辑:比如返回全组Number之和,或返回0,上述代码中已做对应处理。 - 两种方法均能实现需求,方法二更适合数千id的批量处理场景,性能更稳定。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

