如何在Pandas中基于多列并附加AND条件合并DataFrames?
问题描述
我有一段可正常运行的MS SQL代码:
select * from table_1 full outer join table_2 on table_1.Name = table_2.Name_2 and table_1.Qty = table_2.Qty_2 and table_1.[Month] = table_2.Month_2 and table_1.class = 'X' and table_2.class_2 = 'Y'
现在需要在Python中实现相同逻辑,目前写出了如下代码:
df_merge = pd.merge(table_1, table_2, how='outer', left_on=['Name', 'Qty', 'Month'], right_on=['Name_2', 'Qty_2', 'Month_2'])
请问如何在不使用where的情况下,为该合并操作添加and table_1.class = 'X' and table_2.class_2 = 'Y'这两个AND条件?因为使用where会得到不同结果。
解决方案
要实现和SQL中FULL OUTER JOIN ON子句里的额外条件逻辑,不能直接先过滤表再合并(会丢失不满足条件的单边行),也不能合并后直接全局过滤(会丢失所有不匹配的行)。正确的做法是:先执行全外连接,再仅对匹配成功的行应用条件过滤,保留所有单边不匹配的行。
具体实现步骤:
- 执行全外连接时添加
indicator=True参数,让结果表新增_merge列,标记每行是左表独有(left_only)、右表独有(right_only)还是匹配成功(both)。 - 过滤结果:匹配成功的行必须满足
class='X'和class_2='Y',单边独有的行全部保留。
代码示例:
# 执行全外连接并添加匹配标记 df_merge = pd.merge( table_1, table_2, how='outer', left_on=['Name', 'Qty', 'Month'], right_on=['Name_2', 'Qty_2', 'Month_2'], indicator=True ) # 应用条件过滤:保留单边行,或满足条件的匹配行 df_merge = df_merge[ (df_merge['_merge'] != 'both') | ((df_merge['class'] == 'X') & (df_merge['class_2'] == 'Y')) ] # 可选:删除_merge标记列(如果不需要的话) df_merge = df_merge.drop(columns='_merge')
逻辑说明
SQL中FULL OUTER JOIN的ON子句条件仅用于判断两行是否匹配,而非过滤整个结果集:
- 左表中
class!='X'的行、右表中class_2!='Y'的行会被保留,只是不会和对方表的行匹配。 - 只有当左右表行同时满足
class='X'、class_2='Y'且连接键匹配时,才会被视为匹配行。
上述代码完全复现了这个逻辑,避免了先过滤或全局过滤导致的结果差异。
内容的提问来源于stack exchange,提问作者LiAfe
相关产品推荐
相关产品推荐

