pandas DataFrame 数据查询详解:[]、loc、iloc、at、iat 与 ix 用法对比

周末不加班
周末不加班
发布时间:2026-10-13 | 5人浏览过
原创

本文深入解析 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)的简要介绍就到这里,希望能为读者提供参考,也欢迎大家继续支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表