You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:30:32