iloc只认纯整数位置,不接受标签、字符串、浮点数或非法布尔序列,越界或类型错误会直接抛typeerror/valueerror/indexerror。

iloc切片报错最常见的原因:传入了非整数索引或越界位置
直接说结论:iloc 只认**纯整数位置**,不接受标签、字符串、浮点数、布尔序列(除非是布尔数组且长度匹配),也不做任何隐式转换。一旦你写了 df.iloc['A'] 或 df.iloc[1.5:3],立刻抛 TypeError 或 IndexError。
典型错误现象:
-
TypeError: cannot do label indexing on <class> with these indexers [A] of <class></class></class>—— 误把loc的写法套到iloc上 -
IndexError: single positional indexer is out-of-bounds—— 比如df.iloc[100]但 DataFrame 只有 50 行 -
ValueError: Can only index by location with a [integer, integer slice, list-like of integers, boolean array]—— 传了None、np.nan或空列表等非法类型
实操建议:
- 用
df.index和df.columns看清当前索引类型;如果它们是RangeIndex(默认)或纯数字,iloc才“安全” - 不确定时先查位置:
df.index.get_loc('label')转成整数再喂给iloc,而不是硬套 - 切片边界必须是整数或
None:df.iloc[2:5]✅,df.iloc[2.0:5.0]❌
loc按标签索引不是“名字匹配”,而是严格对齐索引对象
loc 看的是索引(index/columns)的**值本身**,不是“看起来像就行”。它底层调用的是索引对象的 .get_loc() 或 .get_indexer() 方法,依赖索引是否可哈希、是否唯一、是否有序。
常见误解场景:
- 索引是
Int64Index(比如[1, 2, 3, 5]),你写df.loc[4]→ 报KeyError,因为 4 不在索引中,哪怕它“数值上接近” - 列名含空格或特殊字符:
df.loc[:, 'user id']必须完全一致,多一个空格就失败 - 用
loc切片时,起止值都必须存在于索引中(闭区间):df.loc[2:5]在[1,2,3,5]上会返回 2、3、5 三行,不含 4(因为没这行),也**不会报错**——这是很多人踩坑的点
实操建议:
- 用
df.index.is_monotonic_increasing检查是否适合用切片;否则优先用布尔索引df[df.index.isin([...])] - 想模糊匹配?别硬靠
loc,改用df.query("col == 'x'")或df.filter(regex='^user') -
loc支持标签列表但不支持元组当单个标签:df.loc[[1,3]]✅,df.loc[(1,3)]❌(除非是 MultiIndex)
混合索引(MultiIndex)下iloc和loc的行为差异更明显
MultiIndex 是最容易暴露两者底层逻辑差别的场景。iloc 始终只看“扁平化后的位置序号”,而 loc 必须传入符合层级结构的元组或切片。
例如 DataFrame 索引是两级 (country, year):
-
df.iloc[0]→ 第 0 行,不管它是 ('CN', 2020) 还是 ('US', 1999) -
df.loc[('CN', 2020)]→ 精确匹配这一对;df.loc['CN']→ 匹配所有 country='CN' 的行(前提是第一级索引可切片) -
df.loc[('CN', [2020, 2021])]❌ 错误:第二级不能直接传列表;得写df.loc[('CN', slice(2020, 2021))]或用xs
性能提示:
-
iloc在 MultiIndex 下几乎无额外开销,纯位置查 -
loc在 MultiIndex 上可能触发树状搜索或哈希查找,若索引未排序(sort_index()没调),速度可能骤降
为什么不能用iloc选列名字符串?因为列索引类型不匹配
这个错误非常高频:df.iloc[:, 'age'] 直接报错。原因很简单:iloc 的列参数也必须是整数位置,而 'age' 是字符串标签 —— 它属于 loc 的管辖范围。
正确做法只有两种:
- 用
loc:df.loc[:, 'age']或df.loc[:, ['age', 'score']] - 先把列名转位置:
col_pos = df.columns.get_loc('age'),再df.iloc[:, col_pos]
注意陷阱:
-
df.columns.get_loc('age')如果列名重复,返回第一个位置;若要找全部,得用np.where(df.columns == 'age')[0] -
df.iloc[:, [0, 2]]是合法的,但df.iloc[:, ['age', 'score']]永远非法 ——iloc不解析列名 - 列顺序变了(比如
reindex或drop后),iloc位置会变,loc标签不变 —— 这是选择依据的关键
底层逻辑一句话收尾:iloc 是 NumPy 式的“内存偏移寻址”,loc 是 Pandas 式的“索引语义寻址”。混淆它们,本质是混淆了数据容器的物理布局和逻辑结构。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











