loc是闭区间、按标签索引,iloc是左闭右开、按位置索引;loc参数为标签(如字符串、日期),iloc仅接受整数;二者坐标系不同,混用必报错。

loc 和 iloc 在切片时最核心的区别就一句话:loc 是闭区间,iloc 是左闭右开——而且它们根本不在同一个坐标系里工作。
切片边界行为完全不同
写 df.loc['a':'c'] 会包含索引为 'a'、'b'、'c' 的所有行(只要这些标签存在且有序);而 df.iloc[1:4] 只取第 1、2、3 行(不包含第 4 行)。这不是“习惯不同”,是设计契约:loc 按语义找范围,iloc 按内存位置数格子。
- 当 index 是默认
RangeIndex且未被修改时,df.loc[0:2]和df.iloc[0:3]看似结果一样,但逻辑完全割裂——前者在查“有没有标签 0/1/2”,后者在拿“第 0/1/2 行” - 一旦你执行过
df = df.drop([1]),df.loc[0:2]可能只返回两行(因为标签 1 缺失),而df.iloc[0:3]依然稳定返回前三行 - 对日期索引,
df.loc['2023-01':'2023-03']合法;df.iloc['2023-01':'2023-03']直接报TypeError
传参类型不能混,一混就报错
你不能把字符串标签塞给 iloc,也不能把整数位置硬塞给 loc——它们的参数校验非常严格。
-
df.iloc['A']→TypeError: cannot do positional indexing,因为iloc只接受整数、切片、布尔数组或整数列表 -
df.loc[0]不是在取“第 0 行”,而是在找 index 值等于0的那一行;如果 index 是['x', 'y', 'z'],这行直接抛KeyError -
df.loc[0, 'colA']和df.iloc[0, df.columns.get_loc('colA')]才是等价写法,后者把列名转成了位置,避免硬编码列号
单元素 vs 列表索引影响返回类型
这个细节在链式操作里极易翻车:类型不对,后续调用 .mean() 或 .plot() 就会静默失败或报错。
-
df.iloc[0]返回Series,df.iloc[[0]]才返回DataFrame -
df.loc['row1']返回Series,df.loc[['row1']]返回DataFrame - 布尔索引也一样:
df.loc[df['x'] > 5]返回DataFrame,但df.iloc[df['x'] > 5]直接报错——iloc不接受布尔序列作为行索引(除非你先把它转成位置数组)
什么时候该换种写法?
真正需要“按位置选行 + 按标签选列”时,别硬套 loc 或 iloc 单层写法。常见替代路径:
- 先用
iloc定行,再用.loc[:, cols]定列:df.iloc[2:5].loc[:, ['A', 'C']] - 更高效:用
df.columns.get_loc()把列名转位置,喂给iloc:df.iloc[2:5, [df.columns.get_loc('A'), df.columns.get_loc('C')]],前提是列名唯一 - 对 MultiIndex,
loc支持元组如df.loc[('A', 'X'), :],iloc仍只认扁平位置,没法直接表达层级语义
最易被忽略的一点:当你写 df.loc[...] 或 df.iloc[...] 的瞬间,脑子里必须明确回答——我在数“第几个”,还是在找“叫什么”。答案错了,后面所有计算都不可信。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











