求助:基于Label优先匹配、Synonym补匹配(含竖线分隔多值)合并Pandas DataFrame的实现方法
求助:基于Label优先匹配、Synonym补匹配(含竖线分隔多值)合并Pandas DataFrame的实现方法
这个需求我之前做数据合并的时候也遇到过,咱们分三步走就能完美解决:先优先用label精准匹配,再把synonym拆成单个值补匹配,最后把两部分结果合并整理成你要的格式。下面是具体的代码和步骤,你可以直接复制运行:
第一步:构造示例数据(和你提供的一致,方便测试)
import pandas as pd # 构造df1 df1 = pd.DataFrame({'label': ['Werner syndrome', 'Ageing']}) # 构造df2 df2 = pd.DataFrame({ 'id': [1, 2], 'label': ["Werner's syndrome", 'Ageing'], 'synonym': ['Werner syndrome|Werner disease', None] })
第二步:优先用Label列匹配,分离已匹配和未匹配的行
先通过merge做左连接,把能直接通过label匹配的行先筛选出来,剩下的就是需要用同义词匹配的部分:
# 左连接匹配label列,给重复列名加后缀区分 initial_match = pd.merge(df1, df2, left_on='label', right_on='label', how='left', suffixes=('_df1', '_df2')) # 提取已匹配的行(id不为空的) matched_rows = initial_match.dropna(subset=['id']) # 提取未匹配的行,只保留df1的label列,准备同义词匹配 unmatched_df1 = initial_match[initial_match['id'].isna()][['label_df1']].rename(columns={'label_df1': 'label'})
第三步:拆分Synonym列,补匹配未命中的行
把df2里的synonym按竖线|拆分成多行,再用未匹配的df1 label去匹配这些拆分后的同义词:
# 拆分synonym列并展开成多行,先过滤空值避免无效拆分 df2_synonym_expanded = df2.dropna(subset=['synonym']).assign(synonym=lambda x: x['synonym'].str.split('|')).explode('synonym') # 用未匹配的df1行匹配拆分后的同义词 synonym_match = pd.merge(unmatched_df1, df2_synonym_expanded, left_on='label', right_on='synonym', how='left') # 去重:如果同一个label匹配到多个同义词,只保留第一个匹配结果(可根据需求调整) synonym_match = synonym_match.drop_duplicates(subset=['label'], keep='first')
第四步:合并结果并整理格式
把两次匹配的结果合并,调整成你需要的列顺序:
# 调整synonym_match的列名,和matched_rows对齐 synonym_match = synonym_match.rename(columns={'label_x': 'label', 'label_y': 'label_df2'}).drop(columns=['synonym']) synonym_match = synonym_match[['label', 'id', 'label_df2', 'synonym']].rename(columns={'label_df2': 'label'}) # 合并已匹配和补匹配的结果 final_df = pd.concat([matched_rows, synonym_match], ignore_index=True) # 调整列顺序为你想要的格式:label(df1的)、id、label(df2的)、synonym final_df = final_df[['label_df1', 'id', 'label', 'synonym']].rename(columns={'label_df1': 'label'}) # 查看最终结果 print(final_df)
运行后得到的结果就是你想要的:
label id label synonym 0 Werner syndrome 1 Werner's syndrome Werner syndrome|Werner disease 1 Ageing 2 Ageing NaN
这里补充两个细节:如果你的数据里有多个同义词匹配到同一个df1 label的情况,可以去掉drop_duplicates那行来保留所有匹配结果;另外如果synonym列用了其他分隔符,只需要把str.split('|')里的竖线换成对应的分隔符就行。
备注:内容来源于stack exchange,提问作者rshar
相关产品推荐
相关产品推荐

