Pandas分组处理:若col_1字符串存在于组内col_2,补全col_2内容
Pandas按
ID分组后匹配col_1与组内col_2并填充的实现 问题描述
我们需要对DataFrame按ID字段分组后,实现以下逻辑:
- 针对每组内的每一行,若该行
col_1的字符串存在于组内任意一行的col_2中(col_2为逗号分隔的字符串) - 则将包含该
col_1字符串的最长/对应完整col_2内容替换当前行的col_2
示例输入数据
import pandas as pd dict_data = { 'ID': {0: 1, 1: 1, 2: 1, 3: 1, 4: 2, 5: 2, 6: 2, 7: 2}, 'col_1': {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'A', 5: 'B', 6: 'C', 7: 'D'}, 'col_2': {0: 'A,B,C', 1: 'A,B', 2: 'C', 3: 'D', 4: 'A,D', 5: 'B', 6: 'C', 7: 'D'} } df = pd.DataFrame.from_dict(dict_data)
当前输出
ID col_1 col_2 0 1 A A,B,C 1 1 B A,B 2 1 C C 3 1 D D 4 2 A A,D 5 2 B B 6 2 C C 7 2 D D
期望输出
ID col_1 col_2 0 1 A A,B,C 1 1 B A,B,C 2 1 C A,B,C 3 1 D D 4 2 A A,D 5 2 B B 6 2 C C 7 2 D A,D
解决方案
通过分组后自定义函数实现,核心思路是先为每组建立col_1元素到对应最长col_2的映射,再批量替换:
def fill_col2(group): # 为组内所有col_2拆分元素,建立元素到对应col_2的映射(优先保留最长的col_2) mapping = {} for _, row in group.iterrows(): elements = row['col_2'].split(',') for elem in elements: # 若元素未记录,或当前col_2比已记录的更长,则更新映射 if elem not in mapping or len(row['col_2']) > len(mapping[elem]): mapping[elem] = row['col_2'] # 根据col_1的值匹配映射,替换col_2,无匹配则保留原内容 group['col_2'] = group['col_1'].map(mapping).fillna(group['col_2']) return group # 按ID分组并应用处理函数 result_df = df.groupby('ID', group_keys=False).apply(fill_col2) print(result_df)
代码解释
- 分组处理函数
fill_col2:- 遍历组内每行,将
col_2按逗号拆分为单个元素,为每个元素绑定对应的col_2内容,优先保留更长的col_2(比如ID=1组中,A/B/C都会映射到最长的A,B,C) - 用
col_1的值匹配映射字典,替换当前行的col_2,未匹配到则保留原内容
- 遍历组内每行,将
- 分组应用:使用
groupby('ID').apply()将函数作用于每个分组,group_keys=False避免生成额外的分组索引
验证结果
运行代码后输出与期望结果完全一致:
ID col_1 col_2 0 1 A A,B,C 1 1 B A,B,C 2 1 C A,B,C 3 1 D D 4 2 A A,D 5 2 B B 6 2 C C 7 2 D A,D
内容的提问来源于stack exchange,提问作者hagder
相关产品推荐
相关产品推荐

