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

Pandas中基于单/多索引时NaN键连接行为不一致问题

Pandas多索引左连接NaN键匹配异常问题解析与解决

现象回顾

当左表使用key_1+key_2的多索引、右表使用key_1的单索引进行左连接时,左表中key_1为NaN的行错误匹配到了右表的desired_value_a,而非预期的NaN;但左表改用单索引时,结果符合预期。

成因分析

这是Pandas 1.4.x版本的设计行为,不是bug。核心原因在于多索引与单索引的连接逻辑差异:

  • 单索引连接时,Pandas严格遵循「NaN不等于任何值(包括自身)」的规则,所以左表NaN键不会匹配到右表的任何行。
  • 多索引连接时,右表的单索引会被广播到左表的所有索引层级进行匹配。对于右表没有的索引层级(这里是key_2),Pandas默认视为「匹配所有值」,包括NaN。这就导致左表key_1为NaN的行,因key_2的NaN被判定为匹配右表的key_1='a'行,最终错误返回desired_value_a。

是否为Bug?

在Pandas 1.4.3中这是既定设计,但在1.5.x及之后的版本中,官方优化了多索引与单索引的连接逻辑,NaN匹配规则会更符合直觉,所以这个问题在新版本中已经被修复。

针对1.4.3版本的解决方案

如果必须保留多索引结构,可通过以下方式实现预期行为:

方法1:显式指定连接键,避免索引连接

先将左表的多索引还原为普通列,仅用key_1作为连接键,完成连接后再重新设置多索引:

import pandas as pd
import numpy as np

left = pd.DataFrame({
    'key_1': ['a', np.nan],
    'key_2': ['a', np.nan],
}).set_index(keys=['key_1', 'key_2'])
right = pd.DataFrame({
    'key_1': ['a', 'b'],
    'desired_column': ['desired_value_a', 'desired_value_b'],
}).set_index(keys=['key_1'])

# 还原索引为列,指定key_1连接后再重建多索引
result = pd.merge(
    left.reset_index(),
    right.reset_index(),
    how='left',
    on='key_1'
).set_index(['key_1', 'key_2'])

方法2:让右表索引结构与左表匹配

给右表添加一个虚拟的key_2索引层级,使其与左表的多索引结构完全对齐,再进行连接:

import pandas as pd
import numpy as np

left = pd.DataFrame({
    'key_1': ['a', np.nan],
    'key_2': ['a', np.nan],
}).set_index(keys=['key_1', 'key_2'])
right = pd.DataFrame({
    'key_1': ['a', 'b'],
    'desired_column': ['desired_value_a', 'desired_value_b'],
}).set_index(keys=['key_1'])

# 给右表添加key_2层级,覆盖左表的所有key_2取值
right_multi = right.reindex(
    pd.MultiIndex.from_product(
        [right.index, left.index.get_level_values(1).unique()],
        names=['key_1', 'key_2']
    )
)

# 结构匹配后再连接
result = pd.merge(
    left,
    right_multi,
    how='left',
    left_index=True,
    right_index=True
)

方法3:升级Pandas版本

如果项目允许,直接升级到Pandas 1.5.x及以上版本,原代码就能直接返回预期结果,无需额外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:10:39