Python的pandas把我坑惨了,原来loc和iloc的区别这么大

简介: 本文详解pandas中`loc`与`iloc`的核心区别:`loc`按**索引标签**定位(切片含右端点、支持布尔索引),`iloc`按**整数位置**定位(左闭右开、不支持布尔索引)。二者在整数索引下行为迥异,混用易致结果偏差却不报错。正确选择可避免数据错位、切片越界等隐蔽bug。(239字)

上个月,同事让我帮他看一段数据处理的代码。逻辑很简单:从一份销售表里取出前 100 行,按地区筛选,然后更新某列的数值。他写完之后跑了一遍,结果对不上,但代码没报错,数据也没缺,就是数字不对。

他把代码发给我,我扫了一眼,问题出在两行上:

df.loc[0:100, 'amount'] = df.loc[0:100, 'amount'] * 1.1

他说:“取前 100 行,乘个 1.1,有什么问题?”

我说:“在 loc 里,0:100 取的是 101 行,不是 100 行。”

他愣了一下:“切片不都是左闭右开吗?”

在 Python 里是,在 pandas 的 loc 里不是。

这就是 lociloc 最容易让人栽跟头的地方。它们的语法看起来几乎一样,都是 df[行, 列] 的形式,但底层逻辑完全不同。一个是按标签找,一个是按位置找。一个切片包含右端点,一个不包含。一个接受任意标签类型,一个只接受整数。

混用它们,代码不会报错,但结果会悄悄偏掉。

代理 IP 使用小技巧 让你的数据抓取效率翻倍 (90).png

最根本的区别:标签 vs 位置

loc 的全称是 location by label,按标签定位。iloc 的全称是 integer location,按整数位置定位。

用一个具体的 DataFrame 来看:

import pandas as pd

df = pd.DataFrame({
   'name': ['Alice', 'Bob', 'Charlie', 'David'],
   'score': [85, 92, 78, 95]
}, index=['a', 'b', 'c', 'd'])

这个 DataFrame 的索引是 'a''b''c''d',位置是 0、1、2、3。

df.loc['b'] 取的是索引为 'b' 的那一行,也就是 Bob。df.iloc[1] 取的是位置为 1 的那一行,也是 Bob。这里两者恰好指向同一行,因为索引标签和位置碰巧对上了。

但如果索引不是默认的 0、1、2、3 呢?比如把索引改成 [10, 20, 30, 40]

df.index = [10, 20, 30, 40]

现在 df.loc[10] 取的是索引为 10 的那一行,也就是第一行 Alice。但 df.iloc[10] 会直接报 IndexError,因为只有 4 行,位置 10 不存在。

反过来,df.iloc[0] 取第一行 Alice,df.loc[0] 会报 KeyError,因为索引里没有 0 这个标签。

这就是核心差异:loc 认的是索引里真实存在的标签,iloc 认的是从 0 开始数的位置编号。两者只在索引恰好是 0、1、2、3……的时候才会重合。一旦索引被设置成日期、字符串、或者乱序的整数,它们就分道扬镳了。

切片行为:loc 包含右端点,iloc 不包含

Python 的切片 list[0:3] 取的是索引 0、1、2,不包含 3。这是大多数人的肌肉记忆。

iloc 遵循这个规则:

df.iloc[0:3]  # 取位置 0、1、2,共 3 行

loc 不一样:

df.loc['a':'c']  # 取 'a'、'b'、'c',共 3 行,包含 'c'

loc 的切片是闭区间,左右都包含。这个设计其实有它的道理:标签是离散的、有意义的,你说“从 a 到 c”,自然应该把 c 也包括进去。而位置是连续的编号,Python 传统上就是左闭右开。

但问题在于,很多人写代码时不会刻意去想这个差异。尤其是当索引是整数的时候:

df = pd.DataFrame({'x': range(10)})
df.loc[0:5]   # 取 0、1、2、3、4、5,共 6 行
df.iloc[0:5]  # 取 0、1、2、3、4,共 5 行

一个取 6 行,一个取 5 行。如果你在循环里用 loc 做分批处理,每批的大小就会比你预期多一行。批次之间还会重叠,因为上一批的末尾和下一批的开头是同一行。

我见过有人在训练模型时用 loc 做数据切分,训练集和验证集有重叠样本,模型评估结果虚高,排查了很久才发现是切片包含右端点导致的。

布尔索引:loc 支持,iloc 不支持

loc 可以直接接受布尔 Series 或布尔数组:

df.loc[df['score'] > 80]

这行代码选出 score 大于 80 的所有行。loc 会把布尔序列对齐到索引上,True 的位置保留,False 的位置丢弃。

iloc 不接受布尔序列。df.iloc[df['score'] > 80] 会报错,因为它期望的是整数位置,不是布尔值。

想在 iloc 里实现同样的效果,得先算出满足条件的行位置:

import numpy as np
positions = np.where(df['score'] > 80)[0]
df.iloc[positions]

麻烦得多,而且容易出错。所以条件筛选基本都用 loc,这是它的主场。

整数索引的歧义

lociloc 最危险的场景,是索引本身就是整数,而且不是从 0 开始的连续整数。

df = pd.DataFrame({'x': [10, 20, 30]}, index=[1, 2, 3])

df.loc[1] 取的是索引为 1 的那一行,也就是 x=10df.iloc[1] 取的是位置为 1 的那一行,也就是 x=20

同样写 [1],一个拿第一行,一个拿第二行。如果代码里混用了 lociloc,或者从别处复制了一段代码但没改定位方式,结果就会错位。

更隐蔽的是 df[1] 这种写法。方括号直接索引在 pandas 里行为很复杂:对列名来说,它取列;对切片来说,它取行;对整数来说,它可能按位置也可能按标签,取决于索引类型。这种模糊性正是 pandas 官方建议永远明确使用 loc 或 iloc 的原因。

赋值时的坑

lociloc 在读取时的差异已经够多了,赋值时更危险。

loc 赋值:

df.loc[df['score'] > 80, 'grade'] = 'A'

这是标准做法,安全、清晰。

iloc 赋值:

df.iloc[0:3, 1] = 0

把位置 0 到 2 的行的第 1 列设为 0。这也有效。

但如果链式使用,比如 df['score'].iloc[0] = 100,pandas 会抛 SettingWithCopyWarning,因为 df['score'] 返回的是一个副本还是一个视图是不确定的,修改可能不会反映到原 DataFrame 上。

loc 在链式赋值时同样有这个问题:df['score'].loc[0] = 100 也会警告。

正确的做法始终是在一次 loc 或 iloc 调用里完成行列定位

df.loc[0, 'score'] = 100
df.iloc[0, 1] = 100

不要先取列再取行,也不要先取行再取列。

一个真实场景

我之前处理一份订单表,索引是订单号,是一串不连续的整数,比如 1001、1003、1007、1012……。我需要做两件事:一是取出前 50 条记录做快速检查,二是把金额大于 1000 的订单标记为高价值。

第一件事我写了:

sample = df.loc[0:50]

结果取出来 51 条,而且因为索引不是从 0 开始的,loc[0:50] 实际匹配的是标签在 0 到 50 之间的行——但这个范围里可能一条都没有,因为订单号是从 1001 开始的。最后返回的是一个空 DataFrame。

正确的写法是:

sample = df.iloc[0:50]

按位置取前 50 条,和索引标签无关。

第二件事我写了:

df.loc[df['amount'] > 1000, 'level'] = 'high'

这个没问题,因为 loc 天然支持布尔索引。

但如果我错误地写成 df.iloc[df['amount'] > 1000, ...],就会直接报错。iloc 不接受布尔序列。

这两个操作放在一起,恰好展示了 loc 和 iloc 各自最适合的场景:按条件筛选用 loc,按位置取数用 iloc

性能差异

lociloc 在性能上也有区别,虽然大多数时候可以忽略,但在大数据集上值得注意。

iloc 按位置定位,底层直接操作 numpy 数组的整数索引,速度最快。

loc 按标签定位,需要先在索引里查找标签对应的位置,多了一步哈希查找或二分查找。对于普通规模的 DataFrame,这个开销可以忽略。但对于几百万行的数据,频繁用 loc 做逐行访问会比 iloc 慢不少。

不过这个差异不应该成为选择依据。正确性永远优先于性能。该用 loc 的地方用 loc,该用 iloc 的地方用 iloc。如果确实遇到性能瓶颈,再考虑把索引转成位置、用 iloc 批量操作,或者直接上 numpy。

一张表说清楚

维度 loc iloc
定位依据 索引标签 整数位置
切片右端点 包含 不包含
布尔索引 支持 不支持
接受类型 标签、标签列表、切片、布尔序列 整数、整数列表、整数切片
索引为整数时 按标签解释 按位置解释
赋值 支持 支持
越界行为 KeyError IndexError

怎么避免踩坑

第一,永远明确写 loc 或 iloc,不要用 df[...] 做模糊索引。方括号的直接索引在 pandas 里行为太多变,读代码的人无法一眼判断是按列还是按行、是按标签还是按位置。

第二,索引不是默认整数时,优先用 iloc 做位置操作。只要你想表达的是“第几行”“前几行”“某几行”,就用 iloc。只要你想表达的是“索引为某个值的行”,就用 loc。

第三,切片时想一想右端点。用 loc 切片,问自己是否真的想包含右端点。用 iloc 切片,确认自己用的是左闭右开的习惯。

第四,条件筛选只用 loc。iloc 不支持布尔序列,硬要绕路只会让代码更难读。

第五,注意索引类型。如果索引是整数,务必清楚 loc 和 iloc 会给出不同结果。可以在代码里加注释说明索引的含义,或者干脆用 reset_index() 把索引变成默认的 0、1、2、3,消除歧义。

最后

lociloc 的区别,本质上是标签语义位置语义的区别。一个回答“哪个标签”,一个回答“第几个”。

它们长得像,但规则不同:切片右端点一个包含一个不包含,布尔索引一个支持一个不支持,整数索引下同一个数字指向不同的行。

这些差异不会让代码报错,只会让结果偏掉。而数据处理的 bug,最难查的就是这种“不报错但不对”的问题。

写 pandas 的时候,每次敲下 lociloc,花一秒钟想一下:我要的是标签还是位置?这一秒钟,能省下后面几个小时的排查。

目录
相关文章
|
12天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
|
12天前
|
人工智能
千问办公官网入口:阿里AI办公QwenWork产品页和免费网页端链接
千问办公官网含两大入口:一是网页端(qwenwork.cn),即开即用,支持浏览器直接访问;二是阿里云产品页 https://t.aliyun.com/U/JNKJuO 提供免费/付费版详情、功能介绍及使用指南。
|
18天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)
|
11天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1372 8
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
|
13天前
|
缓存 人工智能 自然语言处理
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
本文是阿里云百炼平台Qwen3.8-Flash大模型的选型接入指南,作为兼顾性能与响应速度的高性价比多模态模型,它支持百万级上下文窗口、全场景多模态输入与完整智能体能力矩阵,适配编程辅助、智能体协作等核心场景。文中同步梳理了最新下调的阶梯定价、夜间4折等优惠活动,搭配OpenAI兼容流式调用示例,帮助开发者低成本快速落地高并发AI应用。
阿里云qwen3.8-flash大模型介绍:模型能力、模型价格、免费额度与最新活动
|
13天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1984 15
|
17天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1687 4
|
19天前
|
缓存 数据可视化 开发工具
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
DeepSeek Harness 的更新分两层:本体更新(npx 自动最新、npm update -g、源码 git pull)与插件更新(插件市场点更新、命令行覆盖安装)。本文按「准备 → 更新本体 → 更新插件 → 更新后检查」四步走,覆盖新手常见疑问。
2054 1
DeepSeek Harness 怎么更新?dsh 更新完整指南:更新本体(npx、npm、源码)与更新插件两种方式
|
13天前
|
缓存 JSON API
阿里云千问Qwen3.8‑Max深度解析:核心能力、订阅计费规则、API接入配置与生产落地完整教程
Qwen3.8‑Max作为千问系列新一代MoE架构旗舰基座,总参数量达到2.4万亿,激活参数950亿,是面向复杂专业任务、长周期智能体、工程级代码开发、多模态深度解析的高阶大模型,原生支持文本、图像、视频多模态输入,最大上下文窗口达到百万Token,最大输出Token支持131072,内置深度思考推理链路,在编程、科研、法律金融专业分析、长视频文档解析、自主Agent任务等场景能力表现突出。很多开发者在项目前期直接接入该旗舰模型,却对模型能力边界、多种计费模式、订阅套餐权益、API参数配置、上下文缓存优化缺乏完整认知,出现成本失控、接口报错、长文本信息丢失、深度思考模式额外消耗大量Token等
915 3
|
7天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)