Pandas地址DataFrame模糊匹配及跨表提取信息生成新表问题
原代码问题原因
difflib.get_close_matches()接口返回值为列表格式,无匹配结果时返回空列表,你直接调用str()转换后得到的是带方括号、引号的字符串(例如"['123 nice road']"),和df1中存储的纯地址字符串格式完全不一致,因此merge操作无法命中任何匹配项。
可行解决方案
方案1:修正difflib实现逻辑
不用改依赖,直接调整原有代码的返回值处理逻辑即可:
import pandas as pd import difflib # 提前提取df1地址去重列表,减少重复计算 df1_addr_unique = df1['address'].drop_duplicates().tolist() # 提取匹配结果的首个有效值,无匹配则填充空值 df2['matched_addr_df1'] = df2['address'].apply( lambda x: difflib.get_close_matches(x, df1_addr_unique, n=1, cutoff=0.6)[0] if len(difflib.get_close_matches(x, df1_addr_unique, n=1, cutoff=0.6)) > 0 else None ) # 关联df1拉取对应字段生成df3 df3 = df2.merge( df1, left_on='matched_addr_df1', right_on='address', how='left', suffixes=('_df2', '_df1') ) # 按需保留你需要的字段即可
参数说明:cutoff为相似度阈值,取值范围0-1,数值越大匹配要求越严格,可根据实际匹配效果调整。
方案2:使用fuzzywuzzy实现(匹配效果更可控)
针对地址缩写类的格式差异,fuzzywuzzy的模糊匹配适配性更强,首先安装依赖:pip install fuzzywuzzy python-Levenshtein
实现代码:
from fuzzywuzzy import process import pandas as pd df1_addr_unique = df1['address'].drop_duplicates().tolist() def match_addr(addr): # 得分低于70则判定为匹配失败,阈值可自行调整 match_res = process.extractOne(addr, df1_addr_unique, score_cutoff=70) return match_res[0] if match_res else None df2['matched_addr_df1'] = df2['address'].apply(match_addr) # 关联逻辑和方案1一致 df3 = df2.merge( df1, left_on='matched_addr_df1', right_on='address', how='left', suffixes=('_df2', '_df1') )
匹配准确率优化建议
如果地址中存在大量固定缩写,可以先做地址标准化预处理,再执行匹配,准确率会大幅提升:
import re # 定义缩写映射规则,可按需扩充 abbr_mapping = { r'\brd\b': 'road', r'\bdr\b': 'drive', r'\bst\b': 'street', r'\bln\b': 'lane', r'\bpkwy\b': 'parkway' } def normalize_addr(addr): # 统一转小写、去除多余空格 addr = addr.strip().lower() # 替换缩写为全称 for abbr, full in abbr_mapping.items(): addr = re.sub(abbr, full, addr) return addr # 两个表的地址都做标准化处理后,用标准化后的字段匹配即可 df1['norm_addr'] = df1['address'].apply(normalize_addr) df2['norm_addr'] = df2['address'].apply(normalize_addr)
内容的提问来源于stack exchange,提问作者aero8991
相关产品推荐
相关产品推荐

