pd.merge中left_on使用or/and的行为逻辑及多列匹配疑问
问题解析与解决方案
一、为什么left_on=['A' and 'B']只匹配到S7?
Python的逻辑运算符and/or在这里不是作用于DataFrame列的匹配逻辑,而是对字符串做布尔判断后返回结果:
- 非空字符串在布尔语境下被视为
True,空字符串为False 'A' and 'B':由于'A'是True,会直接返回第二个操作数'B',等价于left_on=['B']'A' or 'B':由于'A'是True,会直接返回第一个操作数'A',等价于left_on=['A']
结合你的测试数据:
当left_on=['B']时,df_test_1的B列只有第4行是'S7',而df_test_2的D列恰好存在'S7',因此只有这一行能匹配到E=5;其他行的B列要么是空字符串,要么是不存在于df_test_2的'S6',自然无法匹配。
二、实现"right_on匹配left_on任意列"的左连接
要实现df_test_2的D列匹配df_test_1的A列或B列时完成左连接,可通过以下两种方法实现:
方法1:分两次合并后拼接结果
先分别按A-D、B-D做左连接,再合并两个结果,保留有效匹配的E值:
import pandas as pd df_test_1 = pd.DataFrame({'A':['S1','S2','S3','S4','S5'], 'B':['S6','','','S7',''], 'C':[10,11,12,13,14]}) df_test_2 = pd.DataFrame({'D':['S1','S2','S3','S5','S7','S9'], 'E':[1,2,3,4,5,6]}) # 按A列与D列左连接 merge_a = pd.merge(df_test_1, df_test_2, left_on='A', right_on='D', how='left') # 按B列与D列左连接,仅保留E列用于补充 merge_b = pd.merge(df_test_1, df_test_2, left_on='B', right_on='D', how='left')[['E']] # 合并两个结果,优先保留merge_a的E值,空缺处用merge_b的E值填充 result = merge_a.assign(E=merge_a['E'].combine_first(merge_b['E'])) # 清理多余的D列 result = result.drop(columns=['D']) print(result)
输出结果:
A B C E 0 S1 S6 10 1.0 1 S2 11 2.0 2 S3 12 3.0 3 S4 S7 13 5.0 4 S5 14 4.0
方法2:转长格式后合并再转回宽格式
适合需要匹配多列的场景,先将df_test_1的A/B列转为长格式,合并后再恢复原结构:
# 将A、B列转为长格式,保留C列作为标识 melted = df_test_1.melt(id_vars='C', value_vars=['A','B'], value_name='D') # 与df_test_2合并 merged = pd.merge(melted, df_test_2, on='D', how='left') # 按C列分组,恢复原列结构并取有效E值 result = merged.groupby('C').agg({'A':'first', 'B':'first', 'E':'first'}).reset_index() print(result)
输出结果与方法1一致。
内容的提问来源于stack exchange,提问作者Rajib Lochan Sarkar
相关产品推荐
相关产品推荐

