Pandas合并DataFrame后二次匹配填充NaN缺失值的实现方法
多规则分层合并补全缺失值方案
核心逻辑:放弃依赖索引的combine_first方案,采用分层匹配策略——优先用精度更高的「First Name + 邮箱」规则做第一轮匹配,再针对第一轮未匹配到的行,用「First Name + Last Name」规则做第二轮匹配补全,最后拼接结果,从根源避免行错配、重复问题。
1. 导入依赖并加载原始数据
import pandas as pd import numpy as np df1 = pd.DataFrame([['Elle', 'Kelly', 'ellemoore@email.com', 2], ['Amanda','Johnson', 'johnson.amanda@email.com', 5], ['Jay', 'Rogers', 'jay.rogers@email.com', 4], ['David','Connor', 'famconnor@email.com', 3], ['Rachel','Connor','famconnor@email.com', 2], ['Anne','Smith','anniesmith@email.com', 4], ['Anne','Smith', 'asmith@email.com', 2], ['Dani', 'Carter', 'daniellecarter@email.com', 3], ['Drake', 'Walker', 'dwalker@email.com', 2]], columns = ['First Name', 'Last Name', 'Email', 'Rating']) df2 = pd.DataFrame([[np.nan, np.nan, np.nan, 1040, 'City'], ['Dani','Carter-Hampton', 'daniellecarter@email.com', 1040, 'New York'], ['Anne','Smith','anniesmith@email.com', 1040, 'New York'], ['David', 'Connor', 'famconnor@email.com', 1040, 'Chicago'], ['Jay', 'Rogers','jrogers@email.com', 1040, 'Los Angeles'], ['Anne','Smith', 'asmith@email.com', 1040, 'Houston'], ['Amanda','Johnson','johnson.amanda@email.com', 1040, 'Los Angeles'], ['Rachel', 'Connor', 'famconnor@email.com', 1040, 'Chicago'], ['Elle', 'Moore-Kelly', 'moorekellyentertainment@email.com', 1040, 'Los Angeles'], ['Drake', 'Walker', 'walkerproductions@email.com', 1040, 'Los Angeles']], columns = ['First Name','Last Name','Contact Email','Movie Id','Location'])
2. 第一轮高精度匹配(First Name + 邮箱)
优先用唯一度更高的邮箱字段匹配,保证匹配准确率:
merged_first = df1.merge( df2, left_on = ['First Name', 'Email'], right_on = ['First Name', 'Contact Email'], how = 'right' )
3. 拆分已匹配/未匹配数据,做第二轮姓名维度匹配
第一轮匹配成功的行特征是Rating字段非空(该字段只来自df1),拆分后仅对未匹配部分做第二轮匹配,避免重复计算:
# 拆分数据集 matched_part = merged_first[merged_first['Rating'].notna()].copy() unmatched_part = merged_first[merged_first['Rating'].isna()].copy() # 清理未匹配部分的冗余列,保留df2原始字段 unmatched_part = unmatched_part[df2.columns.tolist()] # 第二轮按First Name + Last Name匹配,仅取需要的Rating字段 merged_second = unmatched_part.merge( df1[['First Name', 'Last Name', 'Rating']], on = ['First Name', 'Last Name'], how = 'left' )
4. 拼接结果并整理格式
# 纵向拼接两部分结果 final_result = pd.concat([matched_part, merged_second], ignore_index=True) # 调整列顺序,对齐期望输出 final_result = final_result[['First Name', 'Last Name', 'Email', 'Rating', 'Contact Email', 'Movie Id', 'Location']]
注意事项:如果业务数据中存在大量同名同姓的重复记录,可以在第二轮合并前对df1做去重处理(比如按时间取最新记录、按Rating取最高记录),避免合并后出现行数膨胀。本次样例数据中重名的Anne Smith已经在第一轮通过邮箱完成精准匹配,第二轮不会出现重复问题。
内容的提问来源于stack exchange,提问作者youaresoconfused
相关产品推荐
相关产品推荐

