pandas DataFrame 数据选取、修改与切片详解
本文详解 pandas DataFrame 的数据选取与切片操作。重点介绍 loc、iloc、ix 及直接索引四种方式的区别与用法,对比布尔索引在 loc 与 iloc 中的表现差异,并指出 ix 已弃用及 chained indexing 风险,帮助开发者高效处理数据。
pandas DataFrame 数据选取概述
初次接触 pandas DataFrame 时,数据的选取、修改和切片操作往往令人困惑。本文总结了几种常用且高效的操作方法,帮助理清思路。
pandas 主要提供了三种核心属性用于选取行或列数据,此外还有直接索引方式。
| 属性名 | 属性 |
|---|---|
| ix | 根据整数索引或者行标签选取数据 |
| iloc | 根据位置的整数索引选取数据 |
| loc | 根据行标签选取数据 |
为了演示具体操作,我们先初始化一个 DataFrame 作为示例。
import numpy as np
import pandas as pd
df = pd.DataFrame([['Snow','M',22],['Tyrion','M',32],['Sansa','F',18],['Arya','F',14]], columns=['name','gender','age'])
该 DataFrame 的数据结构如下所示。
In [35]: df
Out[35]:
name gender age
0 Snow M 22
1 Tyrion M 32
2 Sansa F 18
3 Arya F 14
假设每一列都拥有明确的列名,例如本例中的情况。
In [42]: df.columns
Out[42]: Index(['name', 'gender', 'age'], dtype='object')
直接索引选取整列数据
1. 使用 df['column_name'] 或 df[row_start_index, row_end_index] 可以选取指定的整列数据。
df['name']
df['gender']
df[['name','gender']] #选取多列,多列名字要放在list里
df[0:] #第0行及之后的行,相当于df的全部数据,注意冒号是必须的
df[:2] #第2行之前的数据(不含第2行)
df[0:1] #第0行
df[1:3] #第1行到第2行(不含第3行)
df[-1:] #最后一行
df[-3:-1] #倒数第3行到倒数第1行(不包含最后1行即倒数第1行,这里有点烦躁,因为从前数时从第0行开始,从后数就是-1行开始,毕竟没有-0)
loc 属性与布尔索引
2. loc 属性适用于已知列名的场景,通过 df.loc[index, column] 可以选取指定行和列的数据。
loc 方法提供了五种不同的参数形式,具体用法如下表所示。
| input | example(摘自官方文档) | output |
|---|---|---|
| 行标签 | df.loc[‘viper'] | 选取viper那一行 |
| 行标签数组 | df.loc[[‘viper', ‘sidewinder']] | 选取行标签为viper、sidewinder |
| 行标签切片 | df.loc[‘cobra':‘viper', ‘max_speed'] | 选取从cobra到viper行的max_speed列 |
| 布尔值数组 | df.loc[[False, False, True]] | — |
| 函数 | df.loc[df[‘shield'] > 6, [‘max_speed']] | 选取shield列大于6的那一行的max_speed数据 |
需要注意的是,写法如 df.loc[df['one']>10] 可以正常选出 one 列大于 10 的数据,但需确保逻辑正确。
# df.loc[index, column_name],选取指定行和列的数据
df.loc[0,'name'] # 'Snow'
df.loc[0:2, ['name','age']] #选取第0行到第2行,name列和age列的数据, 注意这里的行选取是包含下标的。
df.loc[[2,3],['name','age']] #选取指定的第2行和第3行,name和age列的数据
df.loc[df['gender']=='M','name'] #选取gender列是M,name列的数据
df.loc[df['gender']=='M',['name','age']] #选取gender列是M,name和age列的数据
iloc 属性与整数定位
3. iloc 适用于列名过长或索引为时间序列等不便输入字符串的情况。iloc(i 代表 index)完全通过数字定位,使用 iloc[row_index, column_index] 进行选取。
iloc 同样提供了五种参数形式,允许通过整数、数组、切片、布尔值或函数进行定位。
| input | example | output |
|---|---|---|
| 整数(行索引) | df.iloc[5] | 选取第6行数据 |
| 整数数组 | df.iloc[[1,3,5]] | 选取第2,4,6行数据 |
| 整数切片 | df.iloc[1:3] | 选取2~4行数据(不包含第4行数据) |
| 布尔值数组 | df.iloc[[True,False,True] | 选取第1,3行数据 |
| 函数 | df.iloc[(df[‘one']>10).tolist()] | 选取'one'这列大于10的那一行数据 |
注意:iloc 接受有返回值的函数作为参数,但必须保证函数返回的是整数、整数列表、布尔值或布尔列表。
如果直接运行 df.iloc[df['one']>10],
则会报错 NotImplementedError: iLocation based boolean indexing on an integer type is not available。
这是因为 df['one'] > 10 返回的是 Series 类型的数据,而 iloc 要求明确的整数索引。
除此之外,还可以进行组合切片操作。
| input | example | output |
|---|---|---|
| 整数(行索引) | df.iloc[5,1] | 选取第6行,第2列的数据 |
| 整数数组 | df.iloc[[1,3],[1,2]] | 选取第2,4行;2,3列的数据 |
| 整数切片 | df.iloc[1:3,1:3] | 选取第2,3行;2,3列的数据 |
| 布尔值数组 | df.iloc[[True,True,False],[True,False,True]] | 选取第1,2行;1,3列的数据 |
切片操作注意事项
需要注意的是,使用 df[参数] 也可以进行切片,但这种方式容易引起 chained indexing(链式索引)问题。此外,df[lable1][lable2] 的操作是线性的,对 lable2 的选取是在 df[lable1] 的基础上进行的,速度相对较慢。因此,在对数据进行切片时,建议尽量使用 iloc 等推荐方法以避免潜在错误。
df.iloc[0,0] #第0行第0列的数据,'Snow'
df.iloc[1,2] #第1行第2列的数据,32
df.iloc[[1,3],0:2] #第1行和第3行,从第0列到第2列(不包含第2列)的数据
df.iloc[1:3,[1,2] #第1行到第3行(不包含第3行),第1列和第2列的数据
ix 方法的弃用与建议
4. ix 方法功能强大,loc 和 iloc 的功能它都能做到,使用 ix[row_index, column_index] 进行选取。
虽然 ix 功能强大,但目前已不再被推荐。在最新版的 pandas 中,ix 已被标记为 deprecated(弃用)(参考 https://github.com/pandas-dev/pandas/issues/14218)。
主要原因在于 ix 可以混合 label(标签)和 position(位置),这导致了许多用户问题和 bug。
因此,最佳实践是:使用 label 时用 loc,使用 position 时用 iloc。
df.ix[0,0] #第0行第0列的数据,'Snow'
df.ix[0,[1,2]] #第0行,第1列和第2列的数据
df.ix[0:2,[1,2]] #第0行到第2行(包含第3行),第1列和第2列的数据
df.ix[1,0:2] #第1行,从第0列到第2列(不包含第2列)的数据
在切片时,iloc 的行索引不含下标上限,而 loc 和 ix 的行索引包含下标上限;列索引方面,iloc 和 ix 都不含列下标上限。这被视为设计上的一个缺憾。
至此,关于 pandas DataFrame 数据选取、修改与切片的实现介绍完毕。如需了解更多相关 pandas 数据选取、修改、切片内容,请搜索本站以前的文章或继续浏览下面的相关文章。希望大家以后多多支持本站!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









