基于子串匹配的Pandas DataFrame关联实现问题
问题描述
现有两个Pandas DataFrame:
a包含Name列b包含ID列
需求:找到a中Name列的值作为子串存在于b中ID列值的记录,将b关联到a上。已知b中每条记录最多匹配a中一条记录,a中记录可匹配b中多条记录。
示例数据
import pandas as pd a = pd.DataFrame({"Name": ["Boomhaur", "Dale", "Bill", "Hank"]}) b = pd.DataFrame({"ID": ["Boomhaur-2345", "Dale-999999", "Bill-000", "Bill-001", "Peggy-420"]})
期望结果
Name ID 0 Boomhaur Boomhaur-2345 1 Dale Dale-999999 2 Bill Bill-000 2 Bill Bill-001 3 Hank NaN
此前在多JSON文件且ID唯一的场景下,曾用以下代码实现,但合并为单一DataFrame后ID无唯一性保障,原有逻辑不再适用,需新的解决方法:
a["_merge"] = a["Name"].apply(lambda x: x in data["ID"]) b = json.normalize(data["Data"]) b["ID"] = data["ID"] b["_merge"] = True a = a.join(b.set_index("_merge"), on="_merge")
解决方案
提供两种适配ID不唯一场景的高效实现方式:
方法一:通用子串匹配法
核心逻辑是为b的每条记录找到对应的Name,再与a做左连接保留所有a的记录:
# 为b添加匹配的Name列,找不到则设为None b['matched_name'] = b['ID'].apply( lambda x: next((name for name in a['Name'] if name in x), None) ) # 左连接a和b,筛选需要的列 result = a.merge(b, left_on='Name', right_on='matched_name', how='left')[['Name', 'ID']]
方法二:前缀提取法(适用于Name是ID前缀的场景)
如果Name始终是ID的前缀(如示例中用-分隔),直接提取前缀匹配效率更高:
# 从ID中提取前缀作为匹配Name b['matched_name'] = b['ID'].str.split('-').str[0] # 左连接得到结果 result = a.merge(b, left_on='Name', right_on='matched_name', how='left')[['Name', 'ID']]
两种方法均可得到符合预期的结果:方法一适用于Name作为任意子串存在的通用场景;方法二在Name是固定前缀的场景下性能更优。
内容的提问来源于stack exchange,提问作者Woody1193
相关产品推荐
相关产品推荐

