如何通过Pandas GroupBy实现分组内基于前序记录的列计算?
Pandas分组计算前序Col_1累加和与最近Col_1=1的Col_2最大值
嘿,我来帮你搞定这个Pandas的分组计算需求!先明确你的核心要求:按id分组,组内先按Col_2排序,然后生成两个新列:
Col_1_Sum:当前行之前所有行的Col_1值之和Col_2_Max:当前行之前最近一次出现Col_1=1的行的Col_2值,没有的话填0
先把你的原始数据用Pandas构造出来,方便复现:
import pandas as pd df = pd.DataFrame({ 'id': [1,1,1,1,1,2,2], 'Col_1': [0,1,1,0,1,0,0], 'Col_2': [21,24,32,35,37,2,5] })
步骤1:先按分组排序
首先必须按id分组,组内按Col_2升序排序,确保后续的“前序行”是符合你要求的顺序:
# 按id分组,组内按Col_2升序排列,重置索引 df_sorted = df.sort_values(['id', 'Col_2']).reset_index(drop=True)
步骤2:计算Col_1_Sum(前序Col_1累加和)
这个需求可以用分组后的shift(1) + cumsum()实现:shift(1)把每个Col_1值向下移动一行,这样当前行对应的就是之前所有行的Col_1值,再用cumsum()累加,最后用fillna(0)处理组内第一行没有前序的情况:
# 分组计算前序Col_1的累加和 df_sorted['Col_1_Sum'] = df_sorted.groupby('id')['Col_1'].apply( lambda x: x.shift(1).cumsum().fillna(0) ).astype(int)
步骤3:计算Col_2_Max(最近Col_1=1的Col_2最大值)
这个需要跟踪最近的有效Col_2值,我们可以分三步处理:
- 先创建辅助列,只保留
Col_1=1的行的Col_2值,其他行设为缺失值 - 分组后用
ffill()向前填充,把最近的有效Col_2值传递给后续行 - 修正组内第一行的特殊情况(不管第一行
Col_1是不是1,Col_2_Max都为0)
代码实现:
# 步骤1:创建辅助列,标记Col_1=1的行的Col_2值 df_sorted['_col2_temp'] = df_sorted.apply( lambda x: x['Col_2'] if x['Col_1'] == 1 else pd.NA, axis=1 ) # 步骤2:分组向前填充最近的有效Col_2值,缺失值填0 df_sorted['Col_2_Max'] = df_sorted.groupby('id')['_col2_temp'].ffill().fillna(0).astype(int) # 步骤3:修正组内第一行的Col_2_Max为0(符合预期结果要求) df_sorted['Col_2_Max'] = df_sorted.groupby('id')['Col_2_Max'].transform( lambda x: x.mask(x.index == x.index[0], 0) ) # 删除辅助列 df_sorted = df_sorted.drop('_col2_temp', axis=1)
最终结果
运行完上面的代码后,输出df_sorted就能得到你想要的结果:
id Col_1 Col_2 Col_1_Sum Col_2_Max 0 1 0 21 0 0 1 1 1 24 0 0 2 1 1 32 1 24 3 1 0 35 2 32 4 1 1 37 2 32 5 2 0 2 0 0 6 2 0 5 0 0
关键要点总结
- 分组内排序是基础:必须先按
id分组,组内按Col_2排序,才能保证“前序行”是你需要的顺序 - 前序累加的技巧:用
shift(1)跳过当前行,再用cumsum()实现分组内的前序累加 - 跟踪最近有效值:通过标记有效行+向前填充,再修正边界情况,就能实现对最近
Col_1=1的Col_2值的跟踪
内容的提问来源于stack exchange,提问作者Soroosh
相关产品推荐
相关产品推荐

