python中pandas的loc和iloc有什么区别?

loc基于标签选择数据,iloc基于整数位置;前者切片包含结束值,适用于有业务含义的索引,后者切片不包含结束值,适合按位置批量操作。

python中pandas的loc和iloc有什么区别?

Pandas中的

loc

iloc

都是用于数据选择的强大工具,但它们的根本区别在于

loc

是基于标签(label-based)进行选择的,而

iloc

则是基于整数位置(integer-location based)进行选择。简单来说,如果你想通过行名和列名来选取数据,就用

loc

;如果你想通过行号和列号(就像Python列表的索引一样)来选取,那就用

iloc

。理解这一点,能帮你避开很多在使用Pandas时可能遇到的坑。

解决方案

要深入理解

loc

iloc

,最好的办法就是看它们在不同场景下的具体行为。它们就像是Pandas数据框的两把不同钥匙,分别对应不同的锁。

loc

:基于标签的选择

loc

操作符主要通过行索引标签和列名来选取数据。它的语法是

df.loc[行标签, 列标签]

。这里有几个关键点:

立即学习“Python免费学习笔记(深入)”;

行标签和列标签可以是单个值,也可以是列表。 比如,

df.loc['row_label_1', 'col_A']

或者

df.loc[['row_label_1', 'row_label_2'], ['col_A', 'col_B']]

切片操作是包含结束值的。 这一点和Python原生的切片(不包含结束值)非常不同。如果你写

df.loc['start_label':'end_label']

,那么

end_label

对应的那一行数据也会被包含在结果中。布尔索引。

loc

非常适合结合布尔条件进行筛选,例如

df.loc[df['col_A'] > 10]

会返回

col_A

列值大于10的所有行。

举个例子:

import pandas as pdimport numpy as np# 创建一个带有自定义索引和列名的数据框data = {    'A': [10, 20, 30, 40, 50],    'B': [1, 2, 3, 4, 5],    'C': [100, 200, 300, 400, 500]}index_labels = ['r1', 'r2', 'r3', 'r4', 'r5']df = pd.DataFrame(data, index=index_labels)print("原始DataFrame:n", df)# 1. 选择单行单列print("nloc: 选择'r2'行和'B'列:n", df.loc['r2', 'B']) # 输出:2# 2. 选择多行多列print("nloc: 选择'r1'到'r3'行和'A'到'C'列:n", df.loc['r1':'r3', 'A':'C'])# 注意,'r3'和'C'都被包含在内# 3. 使用布尔索引print("nloc: 选择'A'列大于20的所有行:n", df.loc[df['A'] > 20])

iloc

:基于整数位置的选择

iloc

操作符则完全依赖于数据的整数位置,和Python列表的索引方式一模一样。它的语法是

df.iloc[行位置, 列位置]

行位置和列位置都是从0开始的整数。 负数索引也有效,例如-1表示最后一行或最后一列。切片操作是不包含结束值的。 这和Python原生的切片行为一致。

df.iloc[0:3]

会选择第0、1、2行,不包含第3行。不支持布尔索引。

iloc

不能直接接受布尔数组作为索引,因为它只认整数位置。

继续上面的例子:

# 1. 选择单行单列print("niloc: 选择第1行(索引为0)和第2列(索引为1):n", df.iloc[0, 1]) # 输出:10 (df.iloc[0,1] 对应 'r1', 'B')# 2. 选择多行多列print("niloc: 选择第0到2行(不包含第3行)和第0到1列(不包含第2列):n", df.iloc[0:3, 0:2])# 对应 'r1', 'r2', 'r3' 行 和 'A', 'B' 列# 3. 使用负数索引print("niloc: 选择最后一行和最后一列:n", df.iloc[-1, -1]) # 输出:500

我个人觉得,当你拿到一个新数据集,想快速预览前几行或者某个特定位置的数据时,

iloc

会更顺手。但如果你在做报表或者处理有明确业务含义的列名和行索引的数据,

loc

的表达力会强得多,也更不容易出错。

为什么

loc

iloc

在处理非默认整数索引时表现不同?

这确实是很多初学者会感到困惑的地方,我自己也曾在这里栽过跟头。问题核心在于,当你的DataFrame索引本身就是整数时,比如

0, 1, 2, ...

loc

iloc

看起来似乎能达到同样的效果,但这只是表象。一旦你的索引不是默认的

0, 1, 2, ...

,或者你故意将索引设置为非连续的整数,甚至重复的整数,它们的行为差异就会立刻显现出来。

loc

始终将你传入的数字视为标签。如果你的DataFrame索引是

[10, 20, 30]

,那么

df.loc[20]

会去寻找标签为

20

的那一行。而

iloc

则始终将你传入的数字视为位置

df.iloc[2]

会去寻找DataFrame中的第3行(因为是从0开始计数)。

来看一个具体的例子,这能更好地说明问题:

data_custom_index = {    'Value': [100, 200, 300, 400]}custom_index = [1, 3, 5, 7] # 自定义整数索引df_custom = pd.DataFrame(data_custom_index, index=custom_index)print("带有自定义整数索引的DataFrame:n", df_custom)# 尝试用loc和iloc选择print("ndf_custom.loc[3]:n", df_custom.loc[3]) # 选择标签为3的行# print(df_custom.loc[2]) # 这一行会报错,因为没有标签为2的行print("ndf_custom.iloc[1]:n", df_custom.iloc[1]) # 选择位置为1(即第二行)的行# 看看它们的不同print("ndf_custom.loc[3]['Value']:", df_custom.loc[3]['Value']) # 输出 200print("df_custom.iloc[1]['Value']:", df_custom.iloc[1]['Value']) # 输出 200# 结果一样是因为碰巧了,但它们的逻辑完全不同# 如果我们想取第0行的值(标签为1)print("ndf_custom.loc[1]['Value']:", df_custom.loc[1]['Value']) # 输出 100print("df_custom.iloc[0]['Value']:", df_custom.iloc[0]['Value']) # 输出 100# 重点来了:# 如果我想要取标签为 5 的那一行,我用 loc[5]print("nloc选择标签为5的行:n", df_custom.loc[5])# 如果我想要取第 2 个位置(从0开始计数,也就是第三行)的那一行,我用 iloc[2]print("niloc选择位置为2的行:n", df_custom.iloc[2])# 它们在数值上是等价的,但概念上完全不同。# loc 找的是索引值等于 5 的那一行,而 iloc 找的是 DataFrame 内部存储顺序上的第三行。

这种区别在数据被重新排序后尤为明显。如果你的DataFrame被排序了,

iloc

仍然会按照新的物理顺序来取数据,而

loc

则会根据标签找到它最初对应的那一行,无论它现在在物理上处于哪个位置。在我看来,这是理解两者最核心的钥匙。

在实际数据分析中,我应该如何选择使用

loc

还是

iloc

选择

loc

还是

iloc

,真的取决于你当前的需求和数据的特性。这不像是一个非此即彼的硬性规定,更像是一种策略选择。

当你的索引有明确的业务含义时,坚决使用

loc

比如,你的DataFrame索引是日期、用户ID、产品SKU等。使用

loc

能让你的代码更具可读性,也更健壮。即使数据顺序被打乱,

loc

也能准确地找到你想要的数据,因为它依赖的是标签而不是物理位置。想象一下,你有一个按日期索引的销售数据,你想查看2023年10月15日的数据,写

df.loc['2023-10-15']

比去算它是第几行要直观和安全得多。当你需要基于位置进行批量操作时,

iloc

是首选。 比如,你只想处理前10行数据,或者去除最后两列。这时候,

iloc

的简洁性就体现出来了。

df.iloc[0:10]

或者

df.iloc[:, :-2]

这种写法,既清晰又高效。在进行数据清洗或特征工程时,经常需要这种基于位置的批量处理。进行布尔索引筛选时,通常与

loc

结合使用。 虽然布尔数组本身可以直接作为索引,但当你想在筛选的同时也指定列时,

loc

的优势就出来了。例如,

df.loc[df['Sales'] > 1000, ['Product', 'Price']]

这种组合非常强大,它能帮你精确地定位到满足特定条件的行和特定的列。如果你需要对数据进行迭代,或者在循环中按顺序处理数据,

iloc

可能更合适。 比如,你可能需要遍历DataFrame的每一行,或者每隔N行取一次数据。在这种场景下,基于整数位置的

iloc

会让你写出更简洁的循环逻辑。

我个人的经验是,在大部分业务分析场景下,我会倾向于使用

loc

。因为数据往往带有丰富的语义信息,利用这些标签能让代码更“说人话”,也更不容易因数据结构变化而失效。只有在确实需要操作数据物理位置,或者进行一些通用性的数据切片时,我才会转向

iloc

。两者结合使用,才是Pandas数据选择的真正艺术。

使用

loc

iloc

时有哪些常见的陷阱和最佳实践?

即便你已经理解了

loc

iloc

的基本区别,在使用过程中还是有一些“坑”需要注意,以及一些能让你的代码更健壮、更高效的最佳实践。

常见陷阱:

切片行为的差异: 这是最常见的陷阱之一。

loc

的切片是包含结束标签的。

df.loc['A':'C']

会包含’A’、’B’、’C’三行(如果它们存在)。

iloc

的切片是不包含结束位置的。

df.iloc[0:3]

会包含第0、1、2行,不包含第3行。这种不一致性经常让人犯错,尤其是在从Python列表操作习惯过渡到Pandas时。

SettingWithCopyWarning

这是一个让无数Pandas用户头疼的问题。当你通过链式索引(例如

df['col_A'][df['col_B'] > 10] = value

)来修改DataFrame时,Pandas可能会发出这个警告。它告诉你,你可能正在修改一个副本,而不是原始DataFrame的视图,导致你的修改没有实际反映到原始数据上。

解决方案: 始终使用

loc

iloc

进行链式赋值操作,并确保它们是单次操作。例如,

df.loc[df['col_B'] > 10, 'col_A'] = value

。这能明确告诉Pandas你想要修改原始DataFrame的特定部分。如果实在需要修改一个副本,就明确地使用

.copy()

整数索引的模糊性: 当DataFrame的索引恰好是

0, 1, 2, ...

这样的整数时,

df.loc[0]

df.iloc[0]

都会返回第一行。这会给人一种错觉,认为它们是等价的。然而,一旦你改变了索引,或者索引不再是连续的整数,这种等价性就会立刻消失。我见过太多人因此而写出在特定数据集上能跑,换个数据集就崩溃的代码。

单元素选择返回Series: 当你使用

loc

iloc

选择单行或单列时,Pandas默认会返回一个Series。如果你期望得到一个DataFrame,可能需要进行额外的处理,例如使用

df.loc[['label']]

(注意双层列表)来确保返回的是一个DataFrame。

最佳实践:

优先使用

loc

处理带有业务含义的索引和列名。 这不仅能提高代码的可读性,还能增加代码的健壮性。你的代码会更清楚地表达“我要选择销售额大于1000的客户的姓名和地址”,而不是“我要选择满足某个条件的第0列和第2列”。

明确指定行和列。 即使你只想选择所有行或所有列,也建议明确使用

:

。例如,

df.loc[:, 'col_A']

df['col_A']

更明确地表达了你是在使用

loc

的行/列选择语法。

避免链式索引进行赋值。 这一点和

SettingWithCopyWarning

紧密相关。总是尝试将选择和赋值操作合并到一次

loc

iloc

调用中。

理解你的索引。 在处理数据之前,花点时间检查DataFrame的索引类型和内容。

df.index

df.columns

是你最好的朋友。了解你的索引是标签还是位置,能帮你避免很多不必要的错误。

在需要时使用

.copy()

如果你确实需要创建一个DataFrame的独立副本进行操作,而不是修改原始数据,请务必使用

.copy()

。例如,

df_copy = df.loc[df['col_A'] > 10].copy()

。这能明确你的意图,并避免潜在的副作用。

通过遵循这些原则,你不仅能更有效地利用

loc

iloc

,还能写出更清晰、更可靠的Pandas代码,这在复杂的数据分析项目中是至关重要的。

以上就是python中pandas的loc和iloc有什么区别?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1370944.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 10:59:35
下一篇 2025年12月14日 10:59:49

相关推荐

发表回复

登录后才能评论
关注微信