pandas loc vs. iloc vs. ix vs. at vs. iat?

时间:2015-02-27 04:12:40

标签: python pandas performance indexing lookup

最近开始从我的安全地点(R)扩展到Python,并且对Pandas中的单元格本地化/选择感到有些困惑。我已经阅读了文档,但我很难理解各种本地化/选择选项的实际意义。

  • 我是否应该使用.loc.iloc而不是.ix
  • 我了解.locilocatiat可能会提供.ix无法提供的保证正确性,但我和#39;还阅读.ix往往是最快的解决方案。
  • 请解释使用.ix以外的任何其他内容的现实世界,最佳做法推理?

5 个答案:

答案 0 :(得分:117)

loc:仅适用于索引
iloc:在职位上工作 ix:您可以从数据框中获取数据而不在索引中 at:获取标量值。这是一个非常快的地方 iat:获取标量值。这是一个非常快的iloc

http://pyciencia.blogspot.com/2015/05/obtener-y-filtrar-datos-de-un-dataframe.html

注意:截至pandas 0.20.0.ix索引器为deprecated,支持更严格的.iloc.loc索引器。

答案 1 :(得分:71)

已更新pandas 0.20,但已弃用ix。这不仅演示了如何使用locilocatiatset_value,还展示了如何使用基于位置/标签的混合索引。< / p>

loc - 基于标签
允许您将1-D数组作为索引器传递。数组可以是索引或列的切片(子集),也可以是布尔数组,其长度与索引或列相等。

特别注意:当标量索引器通过时,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 with 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 :(得分:42)

pandas通过两种主要方式从DataFrame中进行选择。

  • 通过标签
  • 通过整数位置

文档使用术语位置来引用整数位置。我不喜欢这个术语,因为我觉得它很混乱。整数位置更具描述性,正是.iloc所代表的含义。这里的关键词是 INTEGER - 在按整数位置选择时必须使用整数。

在显示摘要之前,请确保...

.ix已弃用且含糊不清,绝不应使用

pandas有三个主要索引器。我们有索引运算符本身(括号 [] ), .loc .iloc 。让我们总结一下:

  • [] - 主要选择列的子集,但也可以选择行。无法同时选择行和列。
  • .loc - 仅按标签选择行和列的子集
  • .iloc - 仅按整数位置选择行和列的子集

我几乎从不使用 .at .iat ,因为它们不会增加任何其他功能,只会增加一点性能。除非你有一个非常时间敏感的应用程序,否则我会阻止它们的使用。无论如何,我们有他们的总结:

  • .at 仅按标签选择DataFrame中的单个标量值
  • .iat 仅按整数位置选择DataFrame中的单个标量值

除了按标签和整数位置选择外,还存在布尔选择,也称为布尔索引

解释.loc.iloc,布尔选择以及.at.iat的示例如下所示

我们将首先关注.loc.iloc之间的差异。在我们讨论差异之前,重要的是要了解DataFrames具有帮助识别每列和每行的标签。我们来看看示例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'])

enter image description here

粗体中的所有字词都是标签。标签agecolorfoodheightscorestate用于 。其他标签JaneNickAaronPenelopeDeanChristinaCornelia用作标签行。这些行标签统称为索引

在DataFrame中选择特定行的主要方法是使用.loc.iloc索引器。这些索引器中的每一个也可用于同时选择列,但现在更容易关注行。此外,每个索引器都使用一组括号,这些括号紧跟其名称后进行选择。

.loc仅按标签

选择数据

我们将首先讨论.loc索引器,它仅通过索引或列标签选择数据。在我们的示例DataFrame中,我们提供了有意义的名称作为索引的值。许多DataFrames没有任何有意义的名称,而是默认只有从0到n-1的整数,其中n是DataFrame的长度。

您可以使用三种不同的输入.loc

  • 一个字符串
  • 字符串列表
  • 使用字符串作为起始值和停止值的切片表示法

使用字符串

选择带有.loc的单行

要选择单行数据,请将索引标签放在.loc后面的括号内。

df.loc['Penelope']

这会将数据行作为Series

返回
age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

使用.loc和字符串列表选择多行

df.loc[['Cornelia', 'Jane', 'Dean']]

这将返回一个DataFrame,其中的行按列表中指定的顺序排列:

enter image description here

使用带有切片表示法的.loc选择多行

切片表示法由开始,停止和步骤值定义。按标签切片时,pandas在返回时包含停止值。以下切片从Aaron到Dean,包括在内。其步长未明确定义,但默认为1。

df.loc['Aaron':'Dean']

enter image description here

复杂切片的采用方式与Python列表相同。

.iloc仅按整数位置选择数据

现在转向.iloc。 DataFrame中的每一行和每列数据都有一个定义它的整数位置。这是在输出中以可视方式显示的标签的补充。整数位置只是从0开始的顶部/左侧的行数/列数。

您可以使用三种不同的输入.iloc

  • 整数
  • 整数列表
  • 使用整数作为起始值和停止值的切片表示法

选择带有整数

的.iloc的单行
df.iloc[4]

这将第5行(整数位置4)作为Series

返回
age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

使用带有整数列表的.iloc选择多行

df.iloc[[2, -2]]

这将返回第三行和第二行到最后一行的DataFrame:

enter image description here

使用带有切片表示法的.iloc选择多行

df.iloc[:5:3]

enter image description here

使用.loc和.iloc

同时选择行和列

.loc/.iloc的一个优秀能力是它们能够同时选择行和列。在上面的示例中,从每个选择中返回所有列。我们可以选择具有与行相同类型输入的列。我们只需要使用逗号分隔行和列选择。

例如,我们可以选择行Jane,而Dean只选择列高度,分数和状态,如下所示:

df.loc[['Jane', 'Dean'], 'height':]

enter image description here

这使用行的标签列表和列

的切片表示法

我们可以自然地使用.iloc仅使用整数执行类似的操作。

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

使用标签和整数位置同时选择

.ix用于与标签和整数位置同时进行选择,这些选项虽然有用但有时令人困惑和含糊不清,幸好它已被弃用。如果您需要使用混合标签和整数位置进行选择,则必须同时选择标签或整数位置。

例如,如果我们想要选择行NickCornelia以及第2列和第4列,我们可以使用.loc将整数转换为带有以下内容的标签:

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

或者,使用get_loc索引方法将索引标签转换为整数。

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

布尔选择

.loc索引器也可以进行布尔选择。例如,如果我们有兴趣查找年龄超过30的所有行并仅返回foodscore列,我们可以执行以下操作:

df.loc[df['age'] > 30, ['food', 'score']] 

您可以使用.iloc复制此内容,但不能将其传递给布尔系列。您必须将布尔系列转换为numpy数组,如下所示:

df.iloc[(df['age'] > 30).values, [2, 4]] 

选择所有行

可以使用.loc/.iloc进行列选择。您可以使用冒号选择所有行:

df.loc[:, 'color':'score':2]

enter image description here

索引操作符[]可以切片,也可以选择行和列,但不能同时选择。

大多数人都熟悉DataFrame索引运算符的主要用途,即选择列。字符串选择单个列作为Series,字符串列表选择多个列作为DataFrame。

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

使用列表选择多列

df[['food', 'score']]

enter image description here

人们不太熟悉的是,当使用切片表示法时,选择是通过行标签或整数位置进行的。这非常令人困惑,我几乎从不使用它,但确实有效。

df['Penelope':'Christina'] # slice rows by label

enter image description here

df[2:6:2] # slice rows by integer location

enter image description here

.loc/.iloc显式选择行是非常优选的。单独的索引操作符无法同时选择行和列。

df[3:5, 'color']
TypeError: unhashable type: 'slice'

.at.iat

进行选择

.at的选择与.loc几乎相同,但它只选择一个单元格&#39;在您的DataFrame中。我们通常将此单元格称为标量值。要使用.loc,请将逗号分隔的行和列标签传递给它。

df.at['Christina', 'color']
'black'

.iat的选择与.iloc几乎相同,但它只选择一个标量值。您必须为行和列位置传递一个整数

df.iat[2, 5]
'FL'

答案 3 :(得分:31)

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 :(得分:3)

让我们从这个小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,我们可以管理子集,并且.at只有一个标量,但.at比.loc快

: - )