如何在Pandas中根据连续累计值分配分组(含重置需求)
解决方案:基于A/B分组生成连续code序列的groupcat
需求说明
给定如下DataFrame:
A B code cumul_sum 0 group1 group1_1 A 1 1 group1 group1_1 A 2 2 group1 group1_1 B 1 3 group1 group1_1 A 1 4 group1 group1_1 A 2 5 group1 group1_1 A 3 6 group2 group2_1 A 1 7 group2 group2_1 A 2 8 group2 group2_1 A 3
需要按A和B列分组,在每组内根据code的连续序列生成groupcat:
- 连续相同的
code序列归为同一个groupcat - 当
code发生变化时,后续序列重新分配新的groupcat编号 - 每个
A/B分组内的groupcat编号从1开始重置
预期结果:
A B code cumul_sum groupcat 0 group1 group1_1 A 1 group1 1 group1 group1_1 A 2 group1 2 group1 group1_1 B 1 group2 3 group1 group1_1 A 1 group3 4 group1 group1_1 A 2 group3 5 group1 group1_1 A 3 group3 6 group2 group2_1 A 1 group1 7 group2 group2_1 A 2 group1 8 group2 group2_1 A 3 group1
代码实现
import pandas as pd # 构造示例DataFrame df = pd.DataFrame({ 'A': ['group1', 'group1', 'group1', 'group1', 'group1', 'group1', 'group2', 'group2', 'group2'], 'B': ['group1_1', 'group1_1', 'group1_1', 'group1_1', 'group1_1', 'group1_1', 'group2_1', 'group2_1', 'group2_1'], 'code': ['A', 'A', 'B', 'A', 'A', 'A', 'A', 'A', 'A'], 'cumul_sum': [1, 2, 1, 1, 2, 3, 1, 2, 3] }) # 1. 标记每组内code的变化点:当前行code与上一行不同则为True,第一行默认标记为变化点 df['change_flag'] = df.groupby(['A', 'B'])['code'].apply(lambda x: x != x.shift()).fillna(True) # 2. 在每组内累加变化标记,得到连续序列的编号 df['group_num'] = df.groupby(['A', 'B'])['change_flag'].cumsum() # 3. 转换为要求的groupcat格式 df['groupcat'] = 'group' + df['group_num'].astype(str) # 清理辅助列(可选) df = df.drop(['change_flag', 'group_num'], axis=1) # 查看结果 print(df)
逻辑解释
- 变化标记:通过
groupby(['A','B'])锁定分组范围,用x != x.shift()对比当前行与上一行的code,判断序列是否中断;第一行因无前置行,用fillna(True)标记为新序列的起点。 - 生成编号:对每组内的变化标记做累加(
cumsum()),每出现一次变化,编号加1,这样就能得到每组内连续code序列的唯一编号。 - 格式转换:将数字编号拼接为
groupX的字符串格式,得到最终的groupcat列。
内容的提问来源于stack exchange,提问作者python_interest
相关产品推荐
相关产品推荐

