如何在Pandas中基于两列匹配将DataFrame B的列追加到A?
解决Pandas多键匹配追加列的问题
为什么你的循环会报错?
你遇到的Can only compare identically-labeled Series objects错误,是因为循环里用了整个A的Series(A['Visit_Date']、A['ID'])和B的Series做对比——两者的索引长度、标签都不一样,Pandas无法直接进行这种非对齐的比较。
而且Pandas的核心优势是矢量化操作,循环遍历行不仅效率极低(数据量大时慢到无法忍受),还容易出现索引、赋值错误,完全不推荐使用。
正确的实现方法:用pd.merge做左连接
直接用Pandas的merge函数,基于ID和Visit_Date两个键做左连接,就能快速把B的Diagnosis列匹配到A中,同时保留A的所有行:
import pandas as pd dict_A = { 'ID': ['A_190792','X_210392','B_050490','F_311291','K_010989'], 'Visit_Date': ['2010-10-31','2011-09-24','2010-01-30','2012-01-01','2013-08-13'], # 修正原数据中的无效日期格式 'Score': [30, 23, 42, 23, 31], } A = pd.DataFrame(dict_A) dict_B = { 'ID': ['G_090891','A_190792','Z_060791','X_210392','B_050490','F_311291','K_010989','F_230989'], 'Visit_Date': ['2013-03-01','2010-10-31','2013-04-03','2011-09-24','2010-01-30','2012-01-01','2013-08-13','2014-09-09'], 'Diagnosis': ['F12', 'G42', 'F34', 'F90', 'G98','G87','F23','G42'], } B = pd.DataFrame(dict_B) # 左连接:保留A的所有行,匹配B中ID和Visit_Date都一致的Diagnosis A_with_diagnosis = pd.merge( A, B[['ID', 'Visit_Date', 'Diagnosis']], # 只取B中需要的列,避免冗余 on=['ID', 'Visit_Date'], how='left' ) print(A_with_diagnosis)
关键参数说明:
on=['ID', 'Visit_Date']:指定两个匹配键,只有当两行的这两个值都完全一致时才会匹配how='left':以A为基准,保留A的所有行;如果A的某行在B中找不到匹配项,Diagnosis列会填充为NaN- 提前筛选B的列:只传入需要的
Diagnosis及匹配键,避免把B的其他无关列合并进来
关于循环的补充说明
如果非要用循环(强烈不推荐),需要修正两个错误:一是用当前行的单个值而非整个Series做判断,二是用正确的索引赋值:
# 仅作错误修正示例,实际开发不要用 A['Diagnosis'] = None for idx, row in A.iterrows(): # 用当前行的ID和日期匹配B match_rows = B[(B['ID'] == row['ID']) & (B['Visit_Date'] == row['Visit_Date'])] if not match_rows.empty: A.loc[idx, 'Diagnosis'] = match_rows['Diagnosis'].iloc[0]
但这种方法在数据量超过万行时,速度会比merge慢几十甚至上百倍,完全没必要舍近求远。
内容的提问来源于stack exchange,提问作者user20501139
相关产品推荐
相关产品推荐

