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

冰火之心
发布: 2025-09-12 12:48:02
原创
645人浏览过
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 pd
import 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']) # 输出 200
print("df_custom.iloc[1]['Value']:", df_custom.iloc[1]['Value']) # 输出 200

# 结果一样是因为碰巧了,但它们的逻辑完全不同
# 如果我们想取第0行的值(标签为1)
print("\ndf_custom.loc[1]['Value']:", df_custom.loc[1]['Value']) # 输出 100
print("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
登录后复制
,真的取决于你当前的需求和数据的特性。这不像是一个非此即彼的硬性规定,更像是一种策略选择。

PatentPal专利申请写作
PatentPal专利申请写作

AI软件来为专利申请自动生成内容

PatentPal专利申请写作 266
查看详情 PatentPal专利申请写作
  • 当你的索引有明确的业务含义时,坚决使用
    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
登录后复制
的基本区别,在使用过程中还是有一些“坑”需要注意,以及一些能让你的代码更健壮、更高效的最佳实践。

常见陷阱:

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

    • loc
      登录后复制
      的切片是包含结束标签的。
      df.loc['A':'C']
      登录后复制
      会包含'A'、'B'、'C'三行(如果它们存在)。
    • iloc
      登录后复制
      的切片是不包含结束位置的。
      df.iloc[0:3]
      登录后复制
      会包含第0、1、2行,不包含第3行。 这种不一致性经常让人犯错,尤其是在从Python列表操作习惯过渡到Pandas时。
  2. 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()
      登录后复制
  3. 整数索引的模糊性: 当DataFrame的索引恰好是

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

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

    loc
    登录后复制
    iloc
    登录后复制
    选择单行或单列时,Pandas默认会返回一个Series。如果你期望得到一个DataFrame,可能需要进行额外的处理,例如使用
    df.loc[['label']]
    登录后复制
    (注意双层列表)来确保返回的是一个DataFrame。

最佳实践:

  1. 优先使用

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

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

    :
    登录后复制
    。例如,
    df.loc[:, 'col_A']
    登录后复制
    df['col_A']
    登录后复制
    更明确地表达了你是在使用
    loc
    登录后复制
    的行/列选择语法。

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

    SettingWithCopyWarning
    登录后复制
    紧密相关。总是尝试将选择和赋值操作合并到一次
    loc
    登录后复制
    iloc
    登录后复制
    调用中。

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

    df.index
    登录后复制
    df.columns
    登录后复制
    是你最好的朋友。了解你的索引是标签还是位置,能帮你避免很多不必要的错误。

  5. 在需要时使用

    .copy()
    登录后复制
    如果你确实需要创建一个DataFrame的独立副本进行操作,而不是修改原始数据,请务必使用
    .copy()
    登录后复制
    。例如,
    df_copy = df.loc[df['col_A'] > 10].copy()
    登录后复制
    。这能明确你的意图,并避免潜在的副作用。

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

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

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

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号