pandas iloc vs ix vs loc解释; 他们有什么不同?

AZh*_*hao 574 python indexing dataframe pandas

有人能解释这三种切片方法有何不同?
我已经看过这些文档了,我已经看到了这些 答案,但我仍然发现自己无法解释三者是如何不同的.对我来说,它们在很大程度上似乎是可以互换的,因为它们处于较低的切片水平.

例如,假设我们想获得a的前五行DataFrame.这三个都是如何运作的?

df.loc[:5]
df.ix[:5]
df.iloc[:5]
Run Code Online (Sandbox Code Playgroud)

有人可以提出三种情况,其中使用的区别更清晰吗?

Ale*_*ley 885

注:在大熊猫版本0.20.0及以上,ix弃用和使用loc,并iloc改为鼓励.我已经将这个答案的部分内容ix完整地描述为早期版本的pandas用户的参考.下面添加了示例,显示了替代方案 ix.


首先,这里是三种方法的概述:

  • loc获取索引中具有特定标签的行(或列).
  • iloc获取索引中特定位置的行(或列)(因此它只需要整数).
  • ix通常尝试表现得像loc但是回退到表现如同iloc索引中不存在标签.

重要的是要注意一些可能使用起来ix有些棘手的细微之处:

  • 如果索引是整数类型,ix则只使用基于标签的索引,而不是回退到基于位置的索引.如果标签不在索引中,则会引发错误.

  • 如果指数不包含唯一整数,然后给出一个整数,ix将立即使用基于位置的索引,而不是基于标签的索引.但是,如果ix给出另一种类型(例如字符串),则可以使用基于标签的索引.


为了说明这三种方法之间的差异,请考虑以下系列:

>>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5])
>>> s
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN
Run Code Online (Sandbox Code Playgroud)

我们将看一下整数值的切片3.

在这种情况下,s.iloc[:3]返回前3行(因为它将3视为一个位置)并s.loc[:3]返回前8行(因为它将3视为标签):

>>> s.iloc[:3] # slice the first three rows
49   NaN
48   NaN
47   NaN

>>> s.loc[:3] # slice up to and including label 3
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN

>>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN
2    NaN
3    NaN
Run Code Online (Sandbox Code Playgroud)

注意s.ix[:3]返回相同的Series,s.loc[:3]因为它首先查找标签而不是处理位置(并且sis是整数类型的索引).

如果我们尝试使用不在索引中的整数标签(比方说6)怎么办?

这里s.iloc[:6]按预期返回系列的前6行.但是,s.loc[:6]由于6不在索引中,因此会引发KeyError .

>>> s.iloc[:6]
49   NaN
48   NaN
47   NaN
46   NaN
45   NaN
1    NaN

>>> s.loc[:6]
KeyError: 6

>>> s.ix[:6]
KeyError: 6
Run Code Online (Sandbox Code Playgroud)

根据上面提到的细微之处,s.ix[:6]现在引发了一个KeyError,因为它试图像在索引中loc找不到一样但却找不到它6.因为我们的索引是整数类型,ix所以不会回归到像iloc.

但是,如果我们的索引是混合类型,给定一个整数ixiloc立即表现而不是引发KeyError:

>>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5])
>>> s2.index.is_mixed() # index is mix of different types
True
>>> s2.ix[:6] # now behaves like iloc given integer
a   NaN
b   NaN
c   NaN
d   NaN
e   NaN
1   NaN
Run Code Online (Sandbox Code Playgroud)

请记住,ix仍然可以接受非整数并且表现得像loc:

>>> s2.ix[:'c'] # behaves like loc given non-integer
a   NaN
b   NaN
c   NaN
Run Code Online (Sandbox Code Playgroud)

作为一般建议,如果您只使用标签进行索引,或仅使用整数位置进行索引,请坚持lociloc避免出现意外结果 - 请勿使用ix.


结合基于位置和基于标签的索引

有时给定一个DataFrame,您需要为行和列混合标签和位置索引方法.

例如,请考虑以下DataFrame.如何最好地将行切割到包括'c' 包含前四列?

>>> df = pd.DataFrame(np.nan, 
                      index=list('abcde'),
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a NaN NaN NaN NaN NaN
b NaN NaN NaN NaN NaN
c NaN NaN NaN NaN NaN
d NaN NaN NaN NaN NaN
e NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)

在早期版本的pandas中(在0.20.0之前)ix让你可以非常巧妙地做到这一点 - 我们可以按标签切片行,按位置切片列(请注意,对于列,ix默认为基于位置的切片,因为 4它不是列名):

>>> df.ix[:'c', :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)

在后续版本的pandas中,我们可以使用iloc另一种方法帮助实现此结果:

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a NaN NaN NaN NaN
b NaN NaN NaN NaN
c NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)

get_loc()是一种索引方法,意思是"获取此索引中标签的位置".请注意,由于切片iloc与其端点不同,如果我们还想要行'c',我们必须将1加到此值.

有在大熊猫的文档进一步的例子在这里.

  • 很棒的解释!我一直有的一个相关问题是loc,iloc和ix与SettingWithCopy警告的关系(如果有的话)?有一些文件,但说实话,我仍然有点困惑http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy (8认同)
  • @measureallthethings:`loc`,`iloc`和`ix`如果被链接在一起,可能仍会触发警告.使用链接文档中的示例DataFrame`dfmi.loc [:,'one'].loc [:,'second']`触发警告就像`dfmi ['one'] ['second']`因为副本第一个索引操作可能返回数据(而不是视图). (2认同)

Joe*_*ron 129

iloc基于整数定位.因此,无论您的行标签是什么,您都可以随时获取第一行

df.iloc[0]
Run Code Online (Sandbox Code Playgroud)

或者做最后五行

df.iloc[-5:]
Run Code Online (Sandbox Code Playgroud)

您也可以在列上使用它.这将检索第3列:

df.iloc[:, 2]    # the : in the first position indicates all rows
Run Code Online (Sandbox Code Playgroud)

您可以将它们组合在一起以获得行和列的交集:

df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns)
Run Code Online (Sandbox Code Playgroud)

另一方面,.loc使用命名索引.让我们设置一个数据框,其中包含字符串作为行标签和列标签:

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])
Run Code Online (Sandbox Code Playgroud)

然后我们可以得到第一行

df.loc['a']     # equivalent to df.iloc[0]
Run Code Online (Sandbox Code Playgroud)

和第二两排的'date'柱通过

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]
Run Code Online (Sandbox Code Playgroud)

等等.现在,值得指出的是,a的默认行和列索引DataFrame是从0开始的整数,在这种情况下iloc,它们loc将以相同的方式工作.这就是为什么你的三个例子是等价的.如果您有一个非数字索引,如字符串或日期时间, df.loc[:5] 将引发错误.

此外,您只需使用数据框即可进行列检索__getitem__:

df['time']    # equivalent to df.loc[:, 'time']
Run Code Online (Sandbox Code Playgroud)

现在假设您要混合位置和命名索引,即使用行上的名称和列上的位置进行索引(澄清一下,我的意思是从我们的数据框中选择,而不是在行索引和整数中创建一个包含字符串的数据框)列索引).这是.ix进来的地方:

df.ix[:2, 'time']    # the first two rows of the 'time' column
Run Code Online (Sandbox Code Playgroud)

我认为值得一提的是你也可以将布尔向量传递给loc方法.例如:

 b = [True, False, True]
 df.loc[b] 
Run Code Online (Sandbox Code Playgroud)

将返回第1行和第3行df.这相当于df[b]选择,但它也可以用于通过布尔向量进行赋值:

df.loc[b, 'name'] = 'Mary', 'John'
Run Code Online (Sandbox Code Playgroud)

  • 确实如此,就像“df.loc[:, :]”一样。它可用于重新分配整个“DataFrame”的值或创建它的视图。 (2认同)

Ted*_*rou 102

在我看来,接受的答案令人困惑,因为它使用只有缺失值的DataFrame.我也不喜欢这个词,基于位置.iloc,相反,喜欢整数位置,因为它是更描述性,正是.iloc代表.关键词是INTEGER - .iloc需要INTEGERS.

有关详细信息,请参阅我关于子集选择的非常详细的


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

因为.ix已弃用,我们只关注.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'])
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

所有粗体字都是标签.标签,age,color,food,height,scorestate被用于.其他标签,Jane,Nick,Aaron,Penelope,Dean,Christina,Cornelia被用于索引.


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

.loc仅按标签选择数据

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

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

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

使用带字符串的.loc选择单行

要选择单行数据,请将索引标签放在以下括号内.loc.

df.loc['Penelope']
Run Code Online (Sandbox Code Playgroud)

这会将数据行作为Series返回

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object
Run Code Online (Sandbox Code Playgroud)

使用带有字符串列表的.loc选择多行

df.loc[['Cornelia', 'Jane', 'Dean']]
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

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

df.loc['Aaron':'Dean']
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

复杂切片可以采用与Python列表相同的方式.

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

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

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

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

使用带整数的.iloc选择单行

df.iloc[4]
Run Code Online (Sandbox Code Playgroud)

这将返回第5行(整数位置4)作为系列

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object
Run Code Online (Sandbox Code Playgroud)

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

df.iloc[[2, -2]]
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

df.iloc[:5:3]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


使用.loc和.iloc同时选择行和列

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

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

df.loc[['Jane', 'Dean'], 'height':]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这使用行的标签列表和列的切片表示法

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

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object
Run Code Online (Sandbox Code Playgroud)

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

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

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

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 
Run Code Online (Sandbox Code Playgroud)

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

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

布尔选择

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

df.loc[df['age'] > 30, ['food', 'score']] 
Run Code Online (Sandbox Code Playgroud)

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

df.iloc[(df['age'] > 30).values, [2, 4]] 
Run Code Online (Sandbox Code Playgroud)

选择所有行

可以.loc/.iloc仅用于列选择.您可以使用冒号选择所有行,如下所示:

df.loc[:, 'color':'score':2]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


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

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

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object
Run Code Online (Sandbox Code Playgroud)

使用列表选择多个列

df[['food', 'score']]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

df['Penelope':'Christina'] # slice rows by label
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

df[2:6:2] # slice rows by integer location
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

df[3:5, 'color']
TypeError: unhashable type: 'slice'
Run Code Online (Sandbox Code Playgroud)

  • 哇,这是我在编程主题中遇到的非常清晰明了的解释之一,您在上一本中解释的关于在行或列上均可使用的普通索引的内容是我们拥有loc和iloc的原因之一方法。我在数据训练营课程中遇到了这一警告。a。)df.columns和df.index返回什么?它是字符串列表吗?如果是列表,是否允许在列表中访问像df.columns [[2,4]]这样的两个元素?b。)我可以在df.columns上调用get_loc()吗?c。)如果是iloc,为什么我们需要调用df ['age']> 30.values。 (4认同)