索引(Indexing)与选择数据:`loc`, `iloc`, `at`, `iat` 的精确使用

索引界的四大天王:loc, iloc, at, iat 的传奇故事 (附带避坑指南)

各位屏幕前的编程英雄们,大家好!我是你们的老朋友,人称Bug终结者、代码段子手、咖啡因爱好者——程序猿阿豪。今天,咱们不聊那些高深的算法,也不谈那些玄乎的架构,咱们聊聊数据分析师和数据科学家们每天都要打交道的“索引”和“选择数据”。

想象一下,你手握着一个巨大的藏宝图(也就是你的DataFrame),里面埋藏着无数的金币(数据)。但是,藏宝图上密密麻麻的标记让你眼花缭乱,你该如何精准地找到你想要的那部分宝藏呢? 这时候,就需要我们的索引界四大天王闪亮登场了!

没错,他们就是:loc, iloc, at, iat。 听起来像不像武侠小说里的四大高手? 他们个个身怀绝技,能帮你从DataFrame中精准地提取数据。 但是,江湖险恶,一不小心就会踩到坑。 今天,阿豪就带大家深入了解这四位大侠, 掌握他们的使用方法,从此告别索引报错,成为数据寻宝达人!

第一回:loc 大侠 – 标签索引的王者

loc 大侠,顾名思义,是基于标签(label)进行索引的。 他就像一个经验丰富的向导,熟悉藏宝图上的每一个地名,只要你告诉他地名,他就能准确地带你找到宝藏。

语法:

df.loc[row_label, column_label]
  • row_label: 行标签(行的名称或索引值)
  • column_label: 列标签(列的名称)

实例演示:

假设我们有一个关于学生成绩的DataFrame,如下所示:

import pandas as pd

data = {'姓名': ['张三', '李四', '王五', '赵六'],
        '语文': [80, 90, 75, 85],
        '数学': [95, 88, 92, 78],
        '英语': [82, 78, 85, 90]}

df = pd.DataFrame(data)
df = df.set_index('姓名') # 将“姓名”列设置为索引
print(df)

输出结果:

     语文  数学  英语
姓名
张三  80  95  82
李四  90  88  78
王五  75  92  85
赵六  85  78  90

现在,我们想找到张三的语文成绩,可以这样写:

zhangsan_yuwen = df.loc['张三', '语文']
print(f"张三的语文成绩是:{zhangsan_yuwen}")

输出结果:

张三的语文成绩是:80

是不是很简单? loc 大侠就像一个精准的定位仪,根据你提供的标签,直接找到对应的数据。

更高级的用法:

loc 不仅可以提取单个数据,还可以提取多行、多列,甚至可以进行切片操作!

  • 提取多行:

    top_students = df.loc[['张三', '李四']] # 提取张三和李四的成绩
    print(top_students)

    输出结果:

       语文  数学  英语
    姓名
    张三  80  95  82
    李四  90  88  78
  • 提取多列:

    chinese_math = df.loc[:, ['语文', '数学']] # 提取所有学生的语文和数学成绩
    print(chinese_math)

    输出结果:

       语文  数学
    姓名
    张三  80  95
    李四  90  88
    王五  75  92
    赵六  85  78
  • 切片操作:

    middle_students = df.loc['李四':'王五'] # 提取李四到王五(包含)的成绩
    print(middle_students)

    输出结果:

       语文  数学  英语
    姓名
    李四  90  88  78
    王五  75  92  85

    注意: loc 的切片操作是包含结束标签的,这一点和Python的列表切片不同!

loc 使用注意事项(避坑指南):

  1. 标签不存在: 如果你提供的标签在DataFrame中不存在,loc 会毫不留情地抛出一个KeyError异常。 所以,在使用 loc 之前,一定要确认你的标签是正确的!

    # 错误的例子
    #df.loc['阿豪', '语文'] # 会报错,因为DataFrame中没有名为“阿豪”的行
  2. 标签类型不一致: loc 严格按照标签类型进行匹配。 如果你的行索引是字符串类型,而你却用整数进行索引,也会报错。

  3. 链式索引的坑: 避免使用链式索引,例如 df['语文']['张三']。 这种写法可能会导致意想不到的错误,而且效率较低。 应该使用 loc 直接定位到目标数据。

    # 错误的例子
    #df['语文']['张三'] # 不推荐使用
    
    # 正确的例子
    df.loc['张三', '语文']

第二回:iloc 大侠 – 位置索引的隐士

iloc 大侠则是一位隐士高手,他不喜欢抛头露面,只用数字来交流。 他是基于整数位置(integer position)进行索引的,就像一个坐标系统,只要你告诉他横纵坐标,他就能准确地找到对应的数据。

语法:

df.iloc[row_index, column_index]
  • row_index: 行索引(整数位置,从0开始)
  • column_index: 列索引(整数位置,从0开始)

实例演示:

还是用上面的学生成绩DataFrame:

print(df)

输出结果:

     语文  数学  英语
姓名
张三  80  95  82
李四  90  88  78
王五  75  92  85
赵六  85  78  90

现在,我们想找到第二行(李四)的第三列(英语)的成绩,可以这样写:

lisi_english = df.iloc[1, 2]
print(f"李四的英语成绩是:{lisi_english}")

输出结果:

李四的英语成绩是:78

更高级的用法:

iloc 同样可以提取多行、多列,以及进行切片操作,用法和 loc 类似,只不过使用的是整数位置。

  • 提取多行:

    first_two_students = df.iloc[[0, 1]] # 提取第一行和第二行的成绩
    print(first_two_students)

    输出结果:

       语文  数学  英语
    姓名
    张三  80  95  82
    李四  90  88  78
  • 提取多列:

    first_two_subjects = df.iloc[:, [0, 1]] # 提取所有学生的语文和数学成绩
    print(first_two_subjects)

    输出结果:

       语文  数学
    姓名
    张三  80  95
    李四  90  88
    王五  75  92
    赵六  85  78
  • 切片操作:

    middle_students = df.iloc[1:3] # 提取第二行到第四行(不包含)的成绩
    print(middle_students)

    输出结果:

       语文  数学  英语
    姓名
    李四  90  88  78
    王五  75  92  85

    注意: iloc 的切片操作是不包含结束位置的,这一点和Python的列表切片一致!

iloc 使用注意事项(避坑指南):

  1. 索引越界: 如果你提供的整数位置超出了DataFrame的范围,iloc 也会毫不留情地抛出一个IndexError异常。 所以,在使用 iloc 之前,一定要确认你的索引没有越界!

    # 错误的例子
    #df.iloc[10, 0] # 会报错,因为DataFrame只有4行
  2. 索引类型错误: iloc 只能接受整数作为索引。 如果你使用字符串或者其他类型进行索引,也会报错。

  3. loc 混淆: ilocloc 的区别在于索引方式不同。 loc 使用标签索引,而 iloc 使用整数位置索引。 一定要分清两者的区别,避免混淆! (阿豪建议:记住 i 代表 integer, 这样就不会弄混啦!😄)

第三回:at 大侠 – 极致性能的刺客

at 大侠是一位追求极致性能的刺客。 他只专注于提取单个数据,速度极快,就像一把锋利的匕首,直击目标。

语法:

df.at[row_label, column_label]
  • row_label: 行标签
  • column_label: 列标签

实例演示:

还是用上面的学生成绩DataFrame:

print(df)

输出结果:

     语文  数学  英语
姓名
张三  80  95  82
李四  90  88  78
王五  75  92  85
赵六  85  78  90

现在,我们想找到王五的数学成绩,可以这样写:

wangwu_math = df.at['王五', '数学']
print(f"王五的数学成绩是:{wangwu_math}")

输出结果:

王五的数学成绩是:92

at 使用注意事项(避坑指南):

  1. 只能提取单个数据: at 只能用于提取单个数据,不能用于提取多行、多列或者进行切片操作。 如果你需要提取多个数据,应该使用 loc 或者 iloc

  2. 标签不存在: 如果你提供的标签在DataFrame中不存在,at 会抛出一个KeyError异常。

  3. 性能优势: at 的优势在于性能。 当你需要频繁地提取单个数据时,at 的效率会比 loc 略高。

第四回:iat 大侠 – 整数坐标的闪电

iat 大侠是 at 的整数位置版本。 他同样追求极致性能,只专注于根据整数位置提取单个数据,速度如闪电般迅捷。

语法:

df.iat[row_index, column_index]
  • row_index: 行索引(整数位置)
  • column_index: 列索引(整数位置)

实例演示:

还是用上面的学生成绩DataFrame:

print(df)

输出结果:

     语文  数学  英语
姓名
张三  80  95  82
李四  90  88  78
王五  75  92  85
赵六  85  78  90

现在,我们想找到第三行(王五)的第二列(数学)的成绩,可以这样写:

wangwu_math = df.iat[2, 1]
print(f"王五的数学成绩是:{wangwu_math}")

输出结果:

王五的数学成绩是:92

iat 使用注意事项(避坑指南):

  1. 只能提取单个数据: iat 只能用于提取单个数据,不能用于提取多行、多列或者进行切片操作。 如果你需要提取多个数据,应该使用 loc 或者 iloc

  2. 索引越界: 如果你提供的整数位置超出了DataFrame的范围,iat 会抛出一个IndexError异常。

  3. 性能优势: iat 的优势在于性能。 当你需要频繁地根据整数位置提取单个数据时,iat 的效率会比 iloc 略高。

总结:四大天王的武功秘籍

为了方便大家记忆,阿豪特意整理了一份四大天王的武功秘籍:

大侠 索引方式 提取数据范围 性能 适用场景
loc 标签 单个/多个/切片 较慢 根据标签选择数据,灵活性高,常用语根据条件筛选数据。
iloc 整数位置 单个/多个/切片 较慢 根据整数位置选择数据,常用于循环遍历DataFrame。
at 标签 单个 最快 根据标签快速提取单个数据,常用于对性能要求较高的场景。
iat 整数位置 单个 最快 根据整数位置快速提取单个数据,常用于对性能要求较高的场景。

选择哪个大侠?

  • 如果你知道数据的标签,并且需要灵活地选择数据(单个、多个、切片),那么 loc 是你的首选。
  • 如果你只知道数据的整数位置,或者需要循环遍历DataFrame,那么 iloc 是你的最佳选择。
  • 如果你需要频繁地提取单个数据,并且对性能要求较高,那么 atiat 可以帮你提升效率。

记住: 没有最好的大侠,只有最适合你的大侠!

终章:数据寻宝之旅

掌握了索引界四大天王的武功秘籍,你就可以在数据海洋中自由驰骋,精准地找到你想要的宝藏。 但是,武功再高,也需要勤加练习。 多写代码,多踩坑,多总结,你才能真正掌握这些技能,成为数据寻宝的专家!

希望今天的分享对大家有所帮助。 如果大家觉得有用,请点赞、评论、转发,让更多的朋友受益。 我是程序猿阿豪,我们下期再见! (ง •̀_•́)ง

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注