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

为何MultiIndex下df.at报KeyError而df.loc无此问题?

MultiIndex下无需指定全层级使用df.at的解决方法

问题重现

普通Index时at可正常取值:

import pandas as pd
df = pd.DataFrame([[0, 2, 3], [0, 4, 1], [10, 20, 30]],
                  index=[4, 5, 6], columns=['A', 'B', 'C'])
print(df.at[4, 'B'])  # 输出2

转为MultiIndex后,直接调用at触发KeyError:

df = df.set_index("A", append=True)
# 执行df.at[4, 'B']会报错KeyError: 4

但loc支持部分索引匹配:

print(df.loc[4, 'B'])
# 输出:
# A
# 0    2
# Name: B, dtype: int64

解决方法

方法1:通过IndexSlice获取行位置后使用at

利用pandas.IndexSlice先定位目标行的整数位置,再传给at:

from pandas import IndexSlice

# 获取第一层级为4的行的位置
row_pos = df.index.get_loc(IndexSlice[4, :])
# 若匹配多行,取第一行的起始位置
if isinstance(row_pos, slice):
    row_pos = row_pos.start

print(df.at[row_pos, 'B'])  # 输出2

方法2:封装辅助函数简化调用

如果需要频繁使用,可以封装函数自动处理部分索引到位置的转换:

def at_partial(df, row_key, col_key):
    # 把单行索引补全为支持前缀匹配的格式
    if not isinstance(row_key, tuple):
        row_key = (row_key,) + (slice(None),) * (df.index.nlevels - 1)
    
    # 获取行位置
    try:
        row_pos = df.index.get_loc(row_key)
    except KeyError:
        raise KeyError(f"找不到匹配的行索引: {row_key}")
    
    # 处理多行匹配的情况,取第一行
    if isinstance(row_pos, slice):
        row_pos = row_pos.start
    
    return df.at[row_pos, col_key]

# 使用示例
print(at_partial(df, 4, 'B'))  # 输出2
print(at_partial(df, (6, 10), 'C'))  # 支持完整索引,输出30

原理说明

  • df.at是精确位置访问器,要求传入的行索引必须是MultiIndex的完整元组,不支持部分前缀匹配;
  • df.loc支持前缀匹配,会自动识别符合部分索引的行;
  • 上述方法通过get_loc将部分索引转换为整数位置,再传递给at实现精确访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:45:18