Pandas按individual_id子集分组合并多行为单行(支持多part)
可兼容多part场景的实现方案
不需要硬编码固定数量的part列,核心思路是先从individual_id中提取出真正用于分组的ID前缀,再通过透视完成长表转宽表的操作,完全适配3个及以上part的情况。
步骤1:拆分原始字段,为分组做准备
从individual_id字符串中拆出两部分内容:用于分组的核心ID(如C11、C12)、当前行对应的part序号。这里用单次拆分的逻辑,避免组ID本身带空格时被错误拆分:
# 匹配" part "关键字做单次拆分,拆成组ID和part编号 df[['group_id', 'part_idx']] = df['individual_id'].str.split(' part ', n=1, expand=True) # 将part编号转为整数,规避字符串排序的常见问题(比如part 10排在part 2之前) df['part_idx'] = df['part_idx'].astype(int) # 按组ID、part编号升序排序,保证后续展开的列顺序和part序号一致 df = df.sort_values(['group_id', 'part_idx']).reset_index(drop=True)
步骤2:透视生成为宽表结构
用pivot函数完成长表转宽表,列会根据实际存在的part数量自动生成,不需要手动指定列名,天然兼容3个及以上part的场景:
# 以group_id为行维度,part_idx为列维度,提取Rec、Sig两个指标值 df_pivot = df.pivot( index='group_id', columns='part_idx', values=['Rec', 'Sig'] )
步骤3:整理列名,输出目标格式
透视结果默认是多级列结构,把列名拼接成题目要求的Rec 1、Sig 2格式,再把行索引转成普通列即可:
# 拼接多级列名为指定格式 df_pivot.columns = [f'{metric} {part}' for metric, part in df_pivot.columns] # 重置索引,把group_id还原为individual_id列 df_final = df_pivot.reset_index(names='individual_id')
补充:用groupby实现的等价写法
如果更习惯用groupby的逻辑,只要把拆分得到的group_id作为分组键,配合组内累计计数生成对应part的列号,再通过unstack展开,同样可以实现目标效果,不需要写循环判断part数量:
# 按组ID分组,组内逐行累计的序号+1就是对应part的列编号 df['part_col'] = df.groupby('group_id').cumcount() + 1 # 锁定索引和取值列,展开为宽表后整理列名 df_final = ( df.set_index(['group_id', 'part_col'])[['Rec', 'Sig']] .unstack('part_col') .rename(columns=lambda col: f'{col[0]} {col[1]}') .reset_index(names='individual_id') )
内容的提问来源于stack exchange,提问作者Screenwriter Marc
相关产品推荐
相关产品推荐

