基于邮政编码的两个DataFrame模糊连接优化问题
解决邮政编码模糊连接的唯一匹配问题
要实现父DataFrame每行匹配子DataFrame中前3位邮政编码相同且相似度/数值最接近的唯一行,你需要在模糊连接后通过分组筛选出每个父行的最优匹配,而非保留所有候选结果。以下是具体实现步骤:
1. 准备依赖与示例数据
import pandas as pd from comparator import JaroWinkler from fuzzyjoin import fuzzy_left_join
构造示例父、子DataFrame:
# 父DataFrame(行数更多) parent_df = pd.DataFrame({ 'parent_id': [1, 2, 3, 4], 'zip_code': ['90210', '10001', '90215', '60601'] }) # 子DataFrame child_df = pd.DataFrame({ 'location': ['Beverly Hills', 'NYC Downtown', 'Beverly Hills North', 'Chicago Loop'], 'zip_code': ['90212', '10003', '90214', '60603'] })
2. 自定义匹配规则:先匹配前3位,再计算JaroWinkler相似度
编写匹配函数,先校验邮政编码前3位是否一致,一致再计算JaroWinkler距离:
def zip_match(parent_zip, child_zip): # 前3位不同直接返回0(不匹配) if parent_zip[:3] != child_zip[:3]: return 0 # 前3位相同则计算JaroWinkler相似度 return JaroWinkler()(parent_zip, child_zip)
3. 模糊连接后筛选最优匹配
先执行模糊连接,保留所有前3位匹配的候选对,再按父行分组,选取相似度最高的唯一匹配:
# 执行模糊左连接,阈值设为0.1确保只保留前3位匹配的结果 fuzzy_merged = fuzzy_left_join( parent_df, child_df, left_on='zip_code', right_on='zip_code', func=zip_match, threshold=0.1 ) # 按父ID分组,筛选相似度最高的行;若相似度相同,取数值最接近的 final_result = fuzzy_merged.sort_values( by=['parent_id', 'similarity'], ascending=[True, False] ).groupby('parent_id').first().reset_index() # 清理冗余列,保留核心数据 final_result = final_result[['parent_id', 'zip_code_x', 'location', 'zip_code_y']] final_result.columns = ['parent_id', 'parent_zip', 'matched_location', 'child_zip']
关键说明
你之前得到多行结果的原因是:fuzzy_left_join会返回所有满足阈值条件的匹配对,而非自动筛选最优项。通过分组+排序取首行的方式,能确保父DataFrame的每一行只保留唯一的最优匹配。如果需要优先数值接近度而非JaroWinkler相似度,可以在排序时加入邮政编码数值差的绝对值作为次要排序条件:
# 新增数值差列 fuzzy_merged['zip_num_diff'] = abs( pd.to_numeric(fuzzy_merged['zip_code_x']) - pd.to_numeric(fuzzy_merged['zip_code_y']) ) # 先按相似度降序,再按数值差升序排序 final_result = fuzzy_merged.sort_values( by=['parent_id', 'similarity', 'zip_num_diff'], ascending=[True, False, True] ).groupby('parent_id').first().reset_index()
内容的提问来源于stack exchange,提问作者Kass
相关产品推荐
相关产品推荐

