pandas DataFrame 数据查询详解:[]、loc、iloc、at、iat 与 ix 用法对比
本文深入解析 pandas 中 DataFrame 的五种核心查询方法:方括号切片、loc、iloc、at 和 iat,并简要提及已弃用的 ix。重点对比各方法在行/列选择、索引与位置定位、单元素访问及赋值安全性的差异,帮助开发者避免 SettingWithCopyWarning 并提升代码执行效率。
pandas 提供了丰富的数据切片工具,但若不熟悉这些方法的细微差别,开发者极易在编码时产生混淆。下文将通过具体示例,逐一阐明各类切片机制的实际应用。
数据介绍
首先,我们随机生成一组测试数据用于后续演示。
In [5]: rnd_1 = [random.randrange(1,20) for x in xrange(1000)]
...: rnd_2 = [random.randrange(1,20) for x in xrange(1000)]
...: rnd_3 = [random.randrange(1,20) for x in xrange(1000)]
...: fecha = pd.date_range('2012-4-10', '2015-1-4')
...:
...: data = pd.DataFrame({'fecha':fecha, 'rnd_1': rnd_1, 'rnd_2': rnd_2, 'rnd_3': rnd_3})
In [6]: data.describe()
Out[6]:
rnd_1 rnd_2 rnd_3
count 1000.000000 1000.000000 1000.000000
mean 9.946000 9.825000 9.894000
std 5.553911 5.559432 5.423484
min 1.000000 1.000000 1.000000
25% 5.000000 5.000000 5.000000
50% 10.000000 10.000000 10.000000
75% 15.000000 15.000000 14.000000
max 19.000000 19.000000 19.000000
[] 切片方法
方括号 [] 可用于对 DataFrame 进行切片,其逻辑类似于 Python 列表的切片操作。通过指定索引,可以实现行选择、列选择或特定区块的选择。
# 行选择
In [7]: data[1:5]
Out[7]:
fecha rnd_1 rnd_2 rnd_3
1 2012-04-11 1 16 3
2 2012-04-12 7 6 1
3 2012-04-13 2 16 7
4 2012-04-14 4 17 7
# 列选择
In [10]: data[['rnd_1', 'rnd_3']]
Out[10]:
rnd_1 rnd_3
0 8 12
1 1 3
2 7 1
3 2 7
4 4 7
5 12 8
6 2 12
7 9 8
8 13 17
9 4 7
10 14 14
11 19 16
12 2 12
13 15 18
14 13 18
15 13 11
16 17 7
17 14 10
18 9 6
19 11 15
20 16 13
21 18 9
22 1 18
23 4 3
24 6 11
25 2 13
26 7 17
27 11 8
28 3 12
29 4 2
.. ... ...
970 8 14
971 19 5
972 13 2
973 8 10
974 8 17
975 6 16
976 3 2
977 12 6
978 12 10
979 15 13
980 8 4
981 17 3
982 1 17
983 11 5
984 7 7
985 13 14
986 6 19
987 13 9
988 3 15
989 19 6
990 7 11
991 11 7
992 19 12
993 2 15
994 10 4
995 14 13
996 12 11
997 11 15
998 17 14
999 3 8
[1000 rows x 2 columns]
# 区块选择
In [11]: data[:7][['rnd_1', 'rnd_2']]
Out[11]:
rnd_1 rnd_2
0 8 17
1 1 16
2 7 6
3 2 16
4 4 17
5 12 19
6 2 7
需要注意的是,在使用方括号进行多列选择时,无法像行选择那样使用类似 1:5 的语法来指定范围。
In [12]: data[['rnd_1':'rnd_3']]
File "<ipython-input-13-6291b6a83eb0>", line 1
data[['rnd_1':'rnd_3']]
^
SyntaxError: invalid syntax
loc
loc 方法允许用户依据索引标签(index labels)来选取行和列。
In [13]: data.loc[1:5]
Out[13]:
fecha rnd_1 rnd_2 rnd_3
1 2012-04-11 1 16 3
2 2012-04-12 7 6 1
3 2012-04-13 2 16 7
4 2012-04-14 4 17 7
5 2012-04-15 12 19 8
这里有一个关键区别:与方括号方法不同,loc 在切片时会包含结束索引对应的行(例如第 5 行),而方括号切片通常只包含到结束索引的前一行(即第 4 行)。
data.loc[2:4, ['rnd_2', 'fecha']] Out[14]: rnd_2 fecha 2 6 2012-04-12 3 16 2012-04-13 4 17 2012-04-14
loc 还支持选取两个特定日期之间的数据,但前提是这两个日期必须作为索引存在于 DataFrame 中。
In [15]: data_fecha = data.set_index('fecha')
...: data_fecha.head()
Out[15]:
rnd_1 rnd_2 rnd_3
fecha
2012-04-10 8 17 12
2012-04-11 1 16 3
2012-04-12 7 6 1
2012-04-13 2 16 7
2012-04-14 4 17 7
In [16]: # 生成两个特定日期
...: fecha_1 = dt.datetime(2013, 4, 14)
...: fecha_2 = dt.datetime(2013, 4, 18)
...:
...: # 生成切片数据
...: data_fecha.loc[fecha_1: fecha_2]
Out[16]:
rnd_1 rnd_2 rnd_3
fecha
2013-04-14 17 10 5
2013-04-15 14 4 9
2013-04-16 1 2 18
2013-04-17 9 15 1
2013-04-18 16 7 17
更新建议:若无特殊需求,强烈建议优先使用 loc 而尽量减少使用 []。这是因为 loc 在对 DataFrame 进行重新赋值时,能有效避免 chained indexing(链式索引)问题;而使用 [] 时,编译器往往会抛出 SettingWithCopy 警告。
更多细节可参考官方文档:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
iloc
如果说 loc 是基于索引值(index values)进行选择,那么 iloc 则是基于索引的位置(integer positions)进行选择。iloc 不关心索引的具体标签是什么,只关注其在序列中的位置序号,因此使用 iloc 时方括号内只能传入整数。
# 行选择
In [17]: data_fecha[10: 15]
Out[17]:
rnd_1 rnd_2 rnd_3
fecha
2012-04-20 14 6 14
2012-04-21 19 14 16
2012-04-22 2 6 12
2012-04-23 15 8 18
2012-04-24 13 8 18
# 列选择
In [18]: data_fecha.iloc[:,[1,2]].head()
Out[18]:
rnd_2 rnd_3
fecha
2012-04-10 17 12
2012-04-11 16 3
2012-04-12 6 1
2012-04-13 16 7
2012-04-14 17 7
# 切片选择
In [19]: data_fecha.iloc[[1,12,34],[0,2]]
Out[19]:
rnd_1 rnd_3
fecha
2012-04-11 1 3
2012-04-22 2 12
2012-05-14 17 10
at
at 的使用方式与 loc 类似,但访问单个元素的速度更快。需要注意的是,at 仅支持访问单个标量元素,不支持访问多个元素。
In [20]: timeit data_fecha.at[fecha_1,'rnd_1'] The slowest run took 3783.11 times longer than the fastest. This could mean that an intermediate result is being cached. 100000 loops, best of 3: 11.3 µs per loop In [21]: timeit data_fecha.loc[fecha_1,'rnd_1'] The slowest run took 121.24 times longer than the fastest. This could mean that an intermediate result is being cached. 10000 loops, best of 3: 192 µs per loop In [22]: data_fecha.at[fecha_1,'rnd_1'] Out[22]: 17
iat
iat 与 iloc 的关系,正如 at 与 loc 的关系一样。它是一种基于索引位置的快速访问方法,同 at 一样,iat 仅能用于访问单个元素。
In [23]: data_fecha.iat[1,0] Out[23]: 1 In [24]: timeit data_fecha.iat[1,0] The slowest run took 6.23 times longer than the fastest. This could mean that an intermediate result is being cached. 100000 loops, best of 3: 8.77 µs per loop In [25]: timeit data_fecha.iloc[1,0] 10000 loops, best of 3: 158 µs per loop
ix
上述几种方法均要求查询的秩(rank)存在于索引中,或者位置不超过数据长度范围。而 ix 方法允许用户获取不在 DataFrame 索引中的特定数据(注:ix 在较新版本 pandas 中已被弃用,此处仅作原理说明)。
In [28]: date_1 = dt.datetime(2013, 1, 10, 8, 30)
...: date_2 = dt.datetime(2013, 1, 13, 4, 20)
...:
...: # 生成切片数据
...: data_fecha.ix[date_1: date_2]
Out[28]:
rnd_1 rnd_2 rnd_3
fecha
2013-01-11 19 17 19
2013-01-12 10 9 17
2013-01-13 15 3 10
如上述示例所示,2013年1月10号并未被选中,因为该时间点被视为 0点0分,早于设定的起始时间 8点30分。
以上关于 pandas 中 DataFrame 查询方法([], loc, iloc, at, iat, ix)的简要介绍就到这里,希望能为读者提供参考,也欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









