如何按规则合并DataFrame多行文本并保留原有顺序?
解决方案:合并DataFrame特定行并保留原顺序与非合并行
核心思路
针对需求,我们需要:
- 对
Merge='merge'的行,以Name末尾带逗号为分组标志,合并同组内的文本 - 保留
Merge='OK'的所有行,且整体结果与原DataFrame的行顺序完全一致
实现代码
import pandas as pd # 示例DataFrame df = pd.DataFrame([ (1, 'john', 'merge'), (1, 'smith,', 'merge'), (1, 'robert', 'merge'), (1, 'g', 'merge'), (1, 'owens,', 'merge'), (2, 'sarah will', 'OK'), (2, 'ali kherad', 'OK'), (2, 'david', 'merge'), (2, 'lu,', 'merge'), ], columns=['ID', 'Name', 'Merge']) # 1. 标记merge组的结束行(Name以逗号结尾的merge行) df['is_end'] = df.apply(lambda x: x['Name'].endswith(',') if x['Merge'] == 'merge' else False, axis=1) # 2. 生成分组键:严格按原行顺序划分分组 df['group_key'] = 0 current_group = 0 current_id = df.iloc[0]['ID'] for idx, row in df.iterrows(): # 切换ID时重置分组计数器 if row['ID'] != current_id: current_id = row['ID'] current_group = 0 # OK行单独作为一个分组 if row['Merge'] == 'OK': current_group += 1 df.at[idx, 'group_key'] = current_group else: # merge行归到当前分组,遇到结束行则递增分组 df.at[idx, 'group_key'] = current_group if row['is_end']: current_group += 1 # 3. 分组聚合:合并文本并整理格式 def merge_names(group): if group['Merge'].iloc[0] == 'OK': return group['Name'].iloc[0] # merge组内拼接文本,去掉每个Name末尾的逗号 return ' '.join([name.rstrip(',') for name in group['Name']]) # 按ID和group_key分组聚合,保留原顺序 result_df = df.groupby(['ID', 'group_key'], as_index=False, sort=False).agg( Name=('Name', merge_names) ).drop(columns='group_key') # 重置索引 result_df = result_df.reset_index(drop=True) print(result_df)
代码说明
- 标记结束行:用
is_end列识别每个merge组的最后一行(Name以逗号结尾),作为分组拆分的依据 - 生成分组键:通过遍历原DataFrame,严格按照行顺序为每一行分配分组键:
- 同一ID内,每个
OK行单独占一个分组 merge行会被归到同一个分组,直到遇到is_end=True的行,才开启新的分组
- 同一ID内,每个
- 分组聚合:
OK行直接保留原Name值merge组内的Name会被去掉末尾逗号后拼接成完整文本
- 保留顺序:
groupby时设置sort=False,保证分组顺序与原数据一致,最终结果的行顺序完全匹配原DataFrame的逻辑顺序
解决的问题
- 避免了原方法丢失
OK行的问题:所有行都会被纳入分组处理 - 解决了大数据量下的顺序错乱:遍历过程严格按原行顺序生成分组键,
sort=False保证分组聚合时不打乱顺序,4000+行的处理效率完全够用
内容的提问来源于stack exchange,提问作者user116936
相关产品推荐
相关产品推荐

