问题:pandas loc vs. iloc vs. ix vs. at vs. iat?
最近开始从我的安全地方(R)分支到Python,并且对中的单元格本地化/选择感到有些困惑Pandas
。我已经阅读了文档,但仍在努力了解各种本地化/选择选项的实际含义。
- 我为什么应该使用
.loc
或.iloc
超过最一般的选择.ix
? - 我的理解是
.loc
,iloc
,at
,和iat
可以提供一些保证正确性是.ix
不能提供的,但我也看到了在那里.ix
往往是一刀切最快的解决方案。 - 请说明使用除
.ix
?以外的任何东西背后的现实世界,最佳实践推理。
回答 0
loc:仅适用于索引
iloc:适用于位置
ix:您可以从数据框获取数据,而无需将其包含在索引
中:获取标量值。这是一个非常快速的定位
:获取标量值。这是一个非常快的iloc
http://pyciencia.blogspot.com/2015/05/obtener-y-filtrar-datos-de-un-dataframe.html
注:由于pandas 0.20.0
中,.ix
索引被弃用赞成更加严格.iloc
和.loc
索引。
回答 1
已更新,pandas
0.20
因为ix
已弃用。这不但表明了如何使用loc
,iloc
,at
,iat
,set_value
,但如何实现,混合位置/标签基于索引。
loc
– 基于标签
允许您将一维数组作为索引器传递。数组可以是索引或列的切片(子集),也可以是长度与索引或列相等的布尔数组。
特别说明:当传递标量索引器时,loc
可以分配以前不存在的新索引或列值。
# label based, but we can use position values
# to get the labels from the index object
df.loc[df.index[2], 'ColName'] = 3
df.loc[df.index[1:3], 'ColName'] = 3
iloc
– 基于位置
类似于,loc
除了位置而不是索引值。但是,您不能分配新的列或索引。
# position based, but we can get the position
# from the columns object via the `get_loc` method
df.iloc[2, df.columns.get_loc('ColName')] = 3
df.iloc[2, 4] = 3
df.iloc[:3, 2:4] = 3
at
– 基于标签的
作品与loc
标量索引器非常相似。 无法对数组索引器进行操作。 能够!分配新的索引和列。
优势比loc
是,这是速度更快。
缺点是不能将数组用于索引器。
# label based, but we can use position values
# to get the labels from the index object
df.at[df.index[2], 'ColName'] = 3
df.at['C', 'ColName'] = 3
iat
– 基于位置的
原理相似iloc
。 无法在数组索引器中工作。 不能!分配新的索引和列。
优势比iloc
是,这是速度更快。
缺点是不能将数组用于索引器。
# position based, but we can get the position
# from the columns object via the `get_loc` method
IBM.iat[2, IBM.columns.get_loc('PNL')] = 3
set_value
– 基于标签的
作品与loc
标量索引器非常相似。 无法对数组索引器进行操作。 能够!分配新的索引和列
优势超级快,因为几乎没有开销!
缺点由于pandas
没有进行大量安全检查,因此开销很少。 使用风险自负。另外,这也不打算供公众使用。
# label based, but we can use position values
# to get the labels from the index object
df.set_value(df.index[2], 'ColName', 3)
set_value
同takable=True
–位置,并根据
原理相似iloc
。 无法在数组索引器中工作。 不能!分配新的索引和列。
优势超级快,因为几乎没有开销!
缺点由于pandas
没有进行大量安全检查,因此开销很少。 使用风险自负。另外,这也不打算供公众使用。
# position based, but we can get the position
# from the columns object via the `get_loc` method
df.set_value(2, df.columns.get_loc('ColName'), 3, takable=True)
回答 2
熊猫从DataFrame中进行选择的主要方式有两种。
- 按标签
- 按整数位置
该文档使用位置一词来指代整数位置。我不喜欢这个术语,因为我觉得它很混乱。整数位置更具描述性,正好.iloc
代表该位置。此处的关键字是INTEGER-按整数位置选择时必须使用整数。
在显示摘要之前,让我们确保…
.ix已弃用且含糊不清,切勿使用
熊猫有三个主要的索引器。我们有索引运算符本身(括号[]
).loc
,和.iloc
。让我们总结一下:
[]
-主要选择列的子集,但也可以选择行。无法同时选择行和列。.loc
-仅按标签选择行和列的子集.iloc
-仅按整数位置选择行和列的子集
我几乎从未使用过,.at
或者.iat
因为它们没有添加任何附加功能并且只增加了一点性能。除非您有一个对时间敏感的应用程序,否则我不建议您使用它们。无论如何,我们有他们的摘要:
.at
仅通过标签在DataFrame中选择单个标量值.iat
仅通过整数位置选择DataFrame中的单个标量值
除了按标签和整数位置进行选择外,还存在布尔选择(也称为布尔索引)。
解释.loc
,,.iloc
布尔选择.at
和.iat
的示例如下所示
我们将首先关注.loc
和之间的差异.iloc
。在讨论差异之前,必须了解DataFrame具有用于帮助标识每一列和每一行的标签,这一点很重要。让我们看一个示例DataFrame:
df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
'height':[165, 70, 120, 80, 180, 172, 150],
'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
},
index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])
所有粗体字均为标签。标签,age
,color
,food
,height
,score
和state
被用于列。其他标签,Jane
,Nick
,Aaron
,Penelope
,Dean
,Christina
,Cornelia
用作标签的行。这些行标签统称为index。
在DataFrame中选择特定行的主要方式是使用.loc
和.iloc
索引器。这些索引器中的每一个也可以用于同时选择列,但是现在只关注行比较容易。此外,每个索引器都使用紧跟其名称的一组括号进行选择。
.loc仅通过标签选择数据
我们将首先讨论.loc
仅通过索引或列标签选择数据的索引器。在示例DataFrame中,我们提供了有意义的名称作为索引值。许多DataFrame都没有任何有意义的名称,而是默认为0到n-1之间的整数,其中n是DataFrame的长度(行数)。
- 一串
- 字符串列表
- 使用字符串作为起始值和终止值的切片符号
用带字符串的.loc选择单行
要选择单行数据,请将索引标签放在后面的括号内.loc
。
df.loc['Penelope']
这将数据行作为系列返回
age 4
color white
food Apple
height 80
score 3.3
state AL
Name: Penelope, dtype: object
使用.loc与字符串列表选择多行
df.loc[['Cornelia', 'Jane', 'Dean']]
这将返回一个DataFrame,其中的数据行按列表中指定的顺序进行:
使用带有切片符号的.loc选择多行
切片符号由开始值,停止值和步长值定义。按标签切片时,大熊猫在返回值中包含停止值。以下是从亚伦到迪恩(含)的片段。它的步长未明确定义,但默认为1。
df.loc['Aaron':'Dean']
可以采用与Python列表相同的方式获取复杂的切片。
.iloc仅按整数位置选择数据
现在转到.iloc
。DataFrame中数据的每一行和每一列都有一个定义它的整数位置。这是输出中直观显示的标签的补充。整数位置就是从0开始从顶部/左侧开始的行数/列数。
- 一个整数
- 整数列表
- 使用整数作为起始值和终止值的切片符号
用带整数的.iloc选择单行
df.iloc[4]
这将返回第5行(整数位置4)为系列
age 32
color gray
food Cheese
height 180
score 1.8
state AK
Name: Dean, dtype: object
用.iloc选择带有整数列表的多行
df.iloc[[2, -2]]
这将返回第三行和倒数第二行的DataFrame:
使用带切片符号的.iloc选择多行
df.iloc[:5:3]
使用.loc和.iloc同时选择行和列
两者的一项出色功能.loc/.iloc
是它们可以同时选择行和列。在上面的示例中,所有列都是从每个选择中返回的。我们可以选择输入类型与行相同的列。我们只需要用逗号分隔行和列的选择即可。
例如,我们可以选择Jane行和Dean行,它们的高度,得分和状态如下:
df.loc[['Jane', 'Dean'], 'height':]
这对行使用标签列表,对列使用切片符号
我们自然可以.iloc
只使用整数来执行类似的操作。
df.iloc[[1,4], 2]
Nick Lamb
Dean Cheese
Name: food, dtype: object
带标签和整数位置的同时选择
.ix
用来与标签和整数位置同时进行选择,这很有用,但有时会造成混淆和模棱两可,值得庆幸的是,它已弃用。如果您需要混合使用标签和整数位置进行选择,则必须同时选择标签或整数位置。
例如,如果我们要选择行Nick
以及第Cornelia
2列和第4列,则可以.loc
通过以下方式将整数转换为标签来使用:
col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names]
或者,可以使用get_loc
index方法将索引标签转换为整数。
labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]
布尔选择
.loc索引器还可以进行布尔选择。例如,如果我们有兴趣查找年龄在30岁以上的所有行并仅返回food
和score
列,则可以执行以下操作:
df.loc[df['age'] > 30, ['food', 'score']]
您可以使用复制它,.iloc
但是不能将其传递为布尔系列。您必须将boolean Series转换为numpy数组,如下所示:
df.iloc[(df['age'] > 30).values, [2, 4]]
选择所有行
可以.loc/.iloc
仅用于列选择。您可以使用冒号选择所有行,如下所示:
df.loc[:, 'color':'score':2]
索引运算符[]
可以切片也可以选择行和列,但不能同时选择。
大多数人都熟悉DataFrame索引运算符的主要目的,即选择列。字符串选择单个列作为系列,字符串列表选择多个列作为DataFrame。
df['food']
Jane Steak
Nick Lamb
Aaron Mango
Penelope Apple
Dean Cheese
Christina Melon
Cornelia Beans
Name: food, dtype: object
使用列表选择多个列
df[['food', 'score']]
人们所不熟悉的是,当使用切片符号时,选择是通过行标签或整数位置进行的。这非常令人困惑,我几乎从未使用过,但是确实可以使用。
df['Penelope':'Christina'] # slice rows by label
df[2:6:2] # slice rows by integer location
.loc/.iloc
选择行的明确性是高度首选的。单独的索引运算符无法同时选择行和列。
df[3:5, 'color']
TypeError: unhashable type: 'slice'
由.at
和选择.iat
选择与.at
几乎相同,.loc
但仅在DataFrame中选择一个“单元”。我们通常将此单元称为标量值。要使用.at
,请将行标签和列标签都传递给它,并用逗号分隔。
df.at['Christina', 'color']
'black'
选择与.iat
几乎相同,.iloc
但仅选择一个标量值。您必须为行和列位置都传递一个整数
df.iat[2, 5]
'FL'
回答 3
df = pd.DataFrame({'A':['a', 'b', 'c'], 'B':[54, 67, 89]}, index=[100, 200, 300])
df
A B
100 a 54
200 b 67
300 c 89
In [19]:
df.loc[100]
Out[19]:
A a
B 54
Name: 100, dtype: object
In [20]:
df.iloc[0]
Out[20]:
A a
B 54
Name: 100, dtype: object
In [24]:
df2 = df.set_index([df.index,'A'])
df2
Out[24]:
B
A
100 a 54
200 b 67
300 c 89
In [25]:
df2.ix[100, 'a']
Out[25]:
B 54
Name: (100, a), dtype: int64
回答 4
让我们从这个小df开始:
import pandas as pd
import time as tm
import numpy as np
n=10
a=np.arange(0,n**2)
df=pd.DataFrame(a.reshape(n,n))
我们会这样
df
Out[25]:
0 1 2 3 4 5 6 7 8 9
0 0 1 2 3 4 5 6 7 8 9
1 10 11 12 13 14 15 16 17 18 19
2 20 21 22 23 24 25 26 27 28 29
3 30 31 32 33 34 35 36 37 38 39
4 40 41 42 43 44 45 46 47 48 49
5 50 51 52 53 54 55 56 57 58 59
6 60 61 62 63 64 65 66 67 68 69
7 70 71 72 73 74 75 76 77 78 79
8 80 81 82 83 84 85 86 87 88 89
9 90 91 92 93 94 95 96 97 98 99
有了这个我们有:
df.iloc[3,3]
Out[33]: 33
df.iat[3,3]
Out[34]: 33
df.iloc[:3,:3]
Out[35]:
0 1 2 3
0 0 1 2 3
1 10 11 12 13
2 20 21 22 23
3 30 31 32 33
df.iat[:3,:3]
Traceback (most recent call last):
... omissis ...
ValueError: At based indexing on an integer index can only have integer indexers
因此,我们不能将.iat用于子集,而只能在其中使用.iloc。
但是,让我们尝试从较大的df中进行选择,并检查速度…
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 7 09:58:39 2018
@author: Fabio Pomi
"""
import pandas as pd
import time as tm
import numpy as np
n=1000
a=np.arange(0,n**2)
df=pd.DataFrame(a.reshape(n,n))
t1=tm.time()
for j in df.index:
for i in df.columns:
a=df.iloc[j,i]
t2=tm.time()
for j in df.index:
for i in df.columns:
a=df.iat[j,i]
t3=tm.time()
loc=t2-t1
at=t3-t2
prc = loc/at *100
print('\nloc:%f at:%f prc:%f' %(loc,at,prc))
loc:10.485600 at:7.395423 prc:141.784987
因此,使用.loc我们可以管理子集,并且仅使用单个标量即可使用.loc,但是.at比.loc更快
:-)