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

如何基于多条件左连接两个Pandas DataFrame并保留左表全部行?

解决左连接并保留左表所有行的条件匹配问题

你原来的代码先做左连接再过滤,会把左表(dat1)中没有满足col2_x < col2_y条件的行直接剔除,这不符合左连接“保留左表所有行”的核心要求。正确的做法应该是保留dat1的全部行,仅对右表(dat2)的匹配结果应用条件过滤,不满足条件的右表列用空值填充。

方法一:保留所有有效匹配明细并补全未匹配行

适合需要完整保留dat2中所有满足条件的匹配记录的场景:

import pandas as pd

dat1 = pd.DataFrame({'col1' : ['AA', 'AA'], 'col2' : [10,20]})
dat2 = pd.DataFrame({'col1' : ['AA', 'BB', 'AA', 'BB'], 'col2' : [11,11,11,11]})

# 给dat1添加原始索引,用于后续找回未匹配的行
dat1_with_idx = dat1.reset_index(names='orig_idx')
# 执行左连接
dat_com = pd.merge(dat1_with_idx, dat2, how='left', on='col1')

# 筛选出满足条件的有效匹配行
valid_matches = dat_com[dat_com['col2_x'] < dat_com['col2_y']]
# 找出dat1中没有有效匹配的行
unmatched_rows = dat1_with_idx[~dat1_with_idx['orig_idx'].isin(valid_matches['orig_idx'])]
# 给未匹配行添加空值的col2_y列
unmatched_rows = unmatched_rows.assign(col2_y=pd.NA)

# 合并结果并恢复原顺序,移除临时索引列
result = pd.concat([valid_matches, unmatched_rows]).sort_values('orig_idx').drop('orig_idx', axis=1)
print(result)

输出结果:

col1  col2_x  col2_y
0   AA      10    11.0
1   AA      10    11.0
3   AA      20     NaN

方法二:简洁处理,合并重复无效匹配

如果不需要保留dat2中重复的满足条件记录,可使用更简洁的方式:

import pandas as pd
import numpy as np

dat1 = pd.DataFrame({'col1' : ['AA', 'AA'], 'col2' : [10,20]})
dat2 = pd.DataFrame({'col1' : ['AA', 'BB', 'AA', 'BB'], 'col2' : [11,11,11,11]})

# 执行左连接
dat_com = pd.merge(dat1, dat2, how='left', on='col1')
# 将不满足条件的col2_y替换为空值
dat_com['col2_y'] = np.where(dat_com['col2_x'] < dat_com['col2_y'], dat_com['col2_y'], pd.NA)
# 去掉同一dat1行对应的重复空值行
result = dat_com.drop_duplicates(subset=['col1', 'col2_x'], keep='first')
print(result)

输出结果:

col1  col2_x  col2_y
0   AA      10    11.0
2   AA      20     NaN

关键说明

左连接的核心是保留左表的所有行,所以不能直接过滤整个结果集,而是要针对右表的匹配结果做条件筛选:

  • 方法一完整保留了dat2中所有符合条件的匹配记录,适合需要明细数据的场景;
  • 方法二合并了重复的无效匹配行,适合只需要确认是否存在匹配的场景。

内容的提问来源于stack exchange,提问作者Brian Smith

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:44:57