如何在Pandas DataFrame中生成符合分组与列值条件的累计计数新列?
Pandas实现按分组累计历史符合条件行数
需求说明
需要为现有DataFrame添加新列col_new,统计**当前行之前(按日期升序)**与当前行col_1、col_2值相同,且col_3值为1的行数(需排除当前行本身)。
原始数据
Date col_1 col_2 col_3 2022-08-20 5 B 1 2022-07-21 6 A 1 2022-07-20 2 A 1 2022-06-15 5 B 1 2022-06-11 3 C 1 2022-06-05 5 C 2 2022-06-01 3 B 2 2022-05-21 6 A 1 2022-05-13 6 A 0 2022-05-10 2 B 3 2022-04-11 2 C 3 2022-03-16 5 A 3 2022-02-20 5 B 1
预期输出
Date col_1 col_2 col_3 col_new 2022-08-20 5 B 1 3 2022-07-21 6 A 1 2 2022-07-20 2 A 1 1 2022-06-15 5 B 1 2 2022-06-11 3 C 1 1 2022-06-05 5 C 2 0 2022-06-01 3 B 2 0 2022-05-21 6 A 1 1 2022-05-13 6 A 0 0 2022-05-10 2 B 3 0 2022-04-11 2 C 3 0 2022-03-16 5 A 3 0 2022-02-20 5 B 1 1
错误代码及问题分析
原代码尝试按日期排序后标记col_3=1的行,再分组累计,但运行时抛出ValueError: Grouper for '<class 'pandas.core.frame.DataFrame'>' not 1-dimensional错误,原因是:
- 分组时使用
df[['col_1','col_2']]作为分组键,但排序后的list_col_3_is_1与原df索引不一致,导致分组键和目标Series无法对齐 - 直接用DataFrame作为分组键处理Series时,Pandas无法识别一维分组逻辑
解决方案
正确的思路是先按日期排序,生成带分组键的临时数据集,分组计算累计和后再映射回原DataFrame:
import pandas as pd # 假设df是原始数据 df['Date'] = pd.to_datetime(df['Date']) # 创建临时数据集,按日期升序排序,标记col_3=1的行,保留分组键 temp_df = df.sort_values('Date').assign( is_target=lambda x: x['col_3'].eq(1) ) # 按col_1和col_2分组,计算累计和,shift(1)排除当前行,填充0 temp_df['col_new'] = temp_df.groupby(['col_1', 'col_2'])['is_target'].cumsum().shift(1).fillna(0).astype(int) # 将结果映射回原DataFrame,保持原始顺序 df = df.merge(temp_df[['Date', 'col_1', 'col_2', 'col_new']], on=['Date', 'col_1', 'col_2'], how='left')
代码说明
- 先将
Date列转为日期类型,确保排序逻辑正确 - 创建临时数据集并按日期升序排序,生成
is_target列标记符合col_3=1的行 - 按
col_1和col_2分组,对is_target做累计求和,再用shift(1)把当前行的累计值下移,实现排除当前行的效果,最后填充空值为0并转为整数 - 通过merge将计算好的
col_new合并回原DataFrame,保证原始行顺序不变
内容的提问来源于stack exchange,提问作者Apook
相关产品推荐
相关产品推荐

