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

基于两列左连接DataFrame:仅将第二表不匹配列设为NaN的实现问题

解决Pandas左连接时仅对不匹配列单独设NaN的问题

需求说明

基于两列对两个DataFrame执行左连接,但要求仅将第二个DataFrame中未匹配的单个列设为NaN,而非整行关联列全部置为NaN。

输入数据

import pandas as pd

df1 = pd.DataFrame({"A": [1, 1, 2, 2, 3], "B": [1, 2, 1, 3, 1]})
df2 = pd.DataFrame({"C": [1, 1, 2, 2], "D": [1, 2, 1, 4]})

预期输出

ABCD
1111
1212
2121
232NaN
31NaNNaN

现有问题

用户尝试了常规的双列匹配左连接:

joined = pd.merge(df1, df2, left_on=['A', 'B'], right_on=['C', 'D'], how='left')

得到的结果中,第4行(索引3)的C和D均为NaN,但预期中C应保留为2,仅D为NaN:

A  B    C    D
0  1  1  1.0  1.0
1  1  2  1.0  2.0
2  2  1  2.0  1.0
3  2  3  NaN  NaN
4  3  1  NaN  NaN

这是因为常规双列连接要求A=C且B=D同时满足才会匹配,而我们需要的是先匹配A=C,再在组内单独判断B与D是否匹配。

解决方案

方法一:分步连接+条件赋值

先基于A和C左连接,再通过条件判断将不匹配的D列设为NaN:

# 第一步:基于A=C左连接,保留df1所有行及对应df2的D值
merged = pd.merge(df1, df2, left_on='A', right_on='C', how='left')
# 第二步:仅保留需要的列,将B≠D的行的D替换为NaN
result = merged[['A', 'B', 'C', 'D']].assign(D=lambda x: x['D'].where(x['B'] == x['D'], pd.NA))

执行结果与预期完全一致:

A  B    C     D
0  1  1  1.0     1
1  1  2  1.0     2
2  2  1  2.0     1
3  2  3  2.0  <NA>
4  3  1  NaN  <NA>

方法二:标记匹配关系后处理

先给df2添加匹配标记,再合并后过滤:

# 给df2添加(A,B)格式的匹配标记
df2['match_key'] = df2.apply(lambda row: (row['C'], row['D']), axis=1)
# 基于A=C左连接
merged = pd.merge(df1, df2, left_on='A', right_on='C', how='left')
# 仅保留匹配成功的D值,否则设为NaN
result = merged.assign(
    D=lambda x: x['D'].where(
        x.apply(lambda row: (row['A'], row['B']) in df2['match_key'].tolist(), axis=1), 
        pd.NA
    )
)[['A', 'B', 'C', 'D']]

两种方法都能实现需求,方法一的效率更高,适合处理大数据集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:07:40