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

二级MultiIndex使用.loc赋值出现NaN的原因及统一赋值方法

Pandas两级MultiIndex赋值出现NaN的原因及统一解决方案

问题现象

在Pandas中对MultiIndex的Series/DataFrame赋值时,仅当MultiIndex为两级且使用标量指定最后一级索引时(如loc[:, 0]),会出现赋值后目标位置变为NaN的情况;而标准索引、三级及以上MultiIndex,或用列表形式指定索引(如loc[:, [0]])时,赋值均正常。

复现代码

import sys
from importlib.metadata import version
import numpy as np
import pandas as pd

print(f"Python version: {sys.version}")
print(f"Pandas version: {version('pandas')}")
print(f"Numpy version: {version('numpy')}\n")

# 标准索引测试
s = pd.Series(np.random.random(5), index=pd.Index(np.arange(5)))
s.loc[0] += 1
print(f"A. 标准索引: .loc[0]\n{s}\n")

# 三级MultiIndex测试
s_multi_3 = pd.Series(np.random.random(5), index=pd.MultiIndex.from_product([["a"], ["b"], np.arange(5)]))
# 转为两级MultiIndex
s_multi_2 = s_multi_3.droplevel(0)

# 两级MultiIndex:用列表指定索引
s_multi_2.loc[:, [0]] += 1
print(f"B1. 两级MultiIndex: .loc[:, [0]]\n{s_multi_2}\n")
# 两级MultiIndex:用标量指定索引(出现NaN)
s_multi_2.loc[:, 0] += 1
print(f"C1. 两级MultiIndex: .loc[:, 0]\n{s_multi_2}\n")

# 三级MultiIndex:用列表指定索引
s_multi_3.loc[:, :, [0]] += 1
print(f"B2. 三级MultiIndex: .loc[:, :, [0]]\n{s_multi_3}\n")
# 三级MultiIndex:用标量指定索引(正常)
s_multi_3.loc[:, :, 0] += 1
print(f"C2. 三级MultiIndex: .loc[:, :, 0]\n{s_multi_3}\n")

输出结果

Python version: 3.12.5 (tags/v3.12.5:ff3bc82, Aug  6 2024, 20:45:27) [MSC v.1940 64 bit (AMD64)]
Pandas version: 2.2.2
Numpy version: 2.0.1

A. 标准索引: .loc[0]
0    1.184514
1    0.460907
2    0.777756
3    0.983770
4    0.722276
dtype: float64

B1. 两级MultiIndex: .loc[:, [0]]
b  0    1.865925
   1    0.728489
   2    0.948691
   3    0.786609
   4    0.756799
dtype: float64

C1. 两级MultiIndex: .loc[:, 0]
b  0         NaN
   1    0.728489
   2    0.948691
   3    0.786609
   4    0.756799
dtype: float64

B2. 三级MultiIndex: .loc[:, :, [0]]
a  b  0    1.865925
      1    0.728489
      2    0.948691
      3    0.786609
      4    0.756799
dtype: float64

C2. 三级MultiIndex: .loc[:, :, 0]
a  b  0    2.865925
      1    0.728489
      2    0.948691
      3    0.786609
      4    0.756799
dtype: float64

原因分析

这是Pandas索引匹配逻辑的歧义性问题:

  • 对于两级MultiIndex,当使用.loc[:, 0]时,Pandas会错误地将标量0解析为一个单元素元组(即(0,)),而非第二级索引的单个值。由于原索引的第二级是整数0,而非元组(0,),导致匹配失败,Pandas会创建新的索引项并赋值,原索引项因未被匹配到,值变为NaN。
  • 对于三级及以上MultiIndex,.loc[:, :, 0]的索引层级明确,Pandas能正确识别0是最后一级的标量索引值,不会产生歧义。
  • 使用列表形式(如[0])时,无论几级MultiIndex,Pandas都会明确将其视为对应层级的索引值列表,匹配逻辑清晰,因此不会出错。

统一赋值方案

以下三种方法可确保在任意层级的MultiIndex中都能正确赋值:

1. 始终使用列表形式指定索引值

将标量索引改为列表形式,消除匹配歧义:

# 两级MultiIndex正确赋值
s_multi_2.loc[:, [0]] += 1

2. 用元组+slice明确指定索引范围

使用slice(None)代替:,结合元组精准定位目标索引区间:

# 匹配第一级所有值、第二级为0的项
s_multi_2.loc[(slice(None), 0)] += 1
# 单个元素精准定位
s_multi_2.loc[('b', 0)] += 1

3. 使用xs方法提取子Series后赋值

xs方法可直接按层级提取子数据集,逻辑直观无歧义:

# 提取第二级索引为0的子Series并赋值
s_multi_2.xs(0, level=1) += 1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 11:44:56