如何在Pandas中对多行关联的分组数据进行去重?
处理跨行分组重复的DataFrame去重问题
现有一组跨行存储的表格数据,部分条目(如Name为M的记录)占用多行。使用drop_duplicates方法仅能处理单行重复,无法去除重复的跨行分组(例如第二个M分组),需求是保留每个Name对应的第一个完整分组,删除后续重复的分组。
示例表格数据
Name Mas Sce M ( (87) 83 (91) (97) ) T (77) 76 R (60) 32 G (95) 20 M ( (50) 89 (50) (99) )
尝试的代码(无法满足需求)
import pandas as pd d = {'Name': ['M', None, None, 'T', 'R', 'G', 'M', '', ''], 'Mas': ['( (87)', '(91)', '(97) )', '(77)', '(60)', '(95)', '( (50)', '(50)', '(99) )'], 'Sce': ['83', '', '', '76', '32', '20', '89', '', '']} df = pd.DataFrame(d) df['Name'] = df['Name'].ffill() print(df) df.drop_duplicates(subset='Name', keep='first', inplace=True) print(df)
期望输出
Name Mas Sce M ( (87) 83 (91) (97) ) T (77) 76 R (60) 32 G (95) 20
解决方案代码
import pandas as pd d = {'Name': ['M', None, None, 'T', 'R', 'G', 'M', '', ''], 'Mas': ['( (87)', '(91)', '(97) )', '(77)', '(60)', '(95)', '( (50)', '(50)', '(99) )'], 'Sce': ['83', '', '', '76', '32', '20', '89', '', '']} df = pd.DataFrame(d) # 统一处理空字符串和空值,用前向填充补全Name列 df['Name'] = df['Name'].replace('', None).ffill() # 标记每个跨行分组的起始行 df['group_start'] = (df['Name'].notna()) & (df['Name'] != df['Name'].shift(1)) # 为每个跨行分组生成唯一ID df['group_id'] = df['group_start'].cumsum() # 获取每个Name对应的第一个分组ID first_group_ids = df.groupby('Name')['group_id'].first().tolist() # 筛选保留第一个分组的所有行,并清理辅助列 result_df = df[df['group_id'].isin(first_group_ids)].drop(columns=['group_start', 'group_id']) # 输出结果 print(result_df)
代码逻辑说明
- 补全Name列:将空字符串转为
None后,用前向填充(ffill)确保同一跨行分组的所有行Name一致。 - 标记分组起始行:通过对比当前行与上一行的Name,识别每个新分组的起始位置。
- 生成分组ID:对起始行标记做累加,为每个跨行分配唯一的组ID。
- 筛选目标行:提取每个Name对应的第一个分组ID,保留这些分组下的所有行,即可实现保留首个完整分组、删除后续重复分组的效果。
内容的提问来源于stack exchange,提问作者user24599509
相关产品推荐
相关产品推荐

