iloc 和 loc 有何不同?

2022-09-05 01:18:50

有人能解释一下这两种切片方法有何不同吗?
我看过这些文档,也看过这些答案,但我仍然发现自己无法理解这三者有何不同。对我来说,它们似乎在很大程度上是可以互换的,因为它们处于较低的切片级别。

例如,假设我们想要获取 .这两者是如何工作的?DataFrame

df.loc[:5]
df.iloc[:5]

有人能提出三种用途区别更清楚的案例吗?


曾几何时,我也想知道这两个功能与熊猫1.0中已经删除了,所以我不再关心了。df.ix[:5]ix


答案 1

标签位置

这两种方法之间的主要区别在于:

  • loc获取具有特定标签的行(和/或列)。

  • iloc获取整数位置处的行(和/或列)。

为了演示,请考虑一系列具有非单调整数索引的字符:s

>>> s = pd.Series(list("abcdef"), index=[49, 48, 47, 0, 1, 2]) 
49    a
48    b
47    c
0     d
1     e
2     f

>>> s.loc[0]    # value at index label 0
'd'

>>> s.iloc[0]   # value at index location 0
'a'

>>> s.loc[0:1]  # rows at index labels between 0 and 1 (inclusive)
0    d
1    e

>>> s.iloc[0:1] # rows at index location between 0 and 1 (exclusive)
49    a

以下是传递各种对象时和传递各种对象时的一些差异/相似之处:s.locs.iloc

<对象> 描述 s.loc[<object>] s.iloc[<object>]
0 单个项目 索引标签处的值(字符串0'd') 索引位置 0 处的值(字符串'a')
0:1 行(标签和01) 行(位置 0 处的第一行)
1:47 具有越界结束的切片 行(空系列) 行(位置 1 开始)
1:47:-1 带负步长的切片 行(标签返回147) 行(空系列)
[2, 0] 整数列表 具有给定标签的 具有给定位置的
s > 'e' 布尔级数(指示哪些值具有该属性) 行(包含'f') NotImplementedError
(s>'e').values 布尔阵列 行(包含'f') 与 相同loc
999 int 对象不在索引中 KeyError IndexError(超出范围)
-1 int 对象不在索引中 KeyError 返回 中的最后一个值s
lambda x: x.index[3] 可调用应用于系列(此处返回索引中的第 3 个项目) s.loc[s.index[3]] s.iloc[s.index[3]]

loc的标签查询功能远远超出了整数索引的范围,值得强调几个其他示例。

下面是一个系列,其中索引包含字符串对象:

>>> s2 = pd.Series(s.index, index=s.values)
>>> s2
a    49
b    48
c    47
d     0
e     1
f     2

由于 是基于标签的,因此它可以使用 获取序列中的第一个值。它还可以使用非整数对象进行切片:locs2.loc['a']

>>> s2.loc['c':'e']  # all rows lying between 'c' and 'e' (inclusive)
c    47
d     0
e     1

对于 DateTime 索引,我们不需要传递按标签获取的确切日期/时间。例如:

>>> s3 = pd.Series(list('abcde'), pd.date_range('now', periods=5, freq='M')) 
>>> s3
2021-01-31 16:41:31.879768    a
2021-02-28 16:41:31.879768    b
2021-03-31 16:41:31.879768    c
2021-04-30 16:41:31.879768    d
2021-05-31 16:41:31.879768    e

然后,要获取 2021 年 3 月/4 月的行,我们只需要:

>>> s3.loc['2021-03':'2021-04']
2021-03-31 17:04:30.742316    c
2021-04-30 17:04:30.742316    d

行和列

loc并且使用数据帧的工作方式与使用序列的方式相同。请注意,这两种方法都可以同时处理列和行。iloc

给定元组时,第一个元素用于为行编制索引,如果存在,则第二个元素用于为列编制索引。

考虑下面定义的数据帧:

>>> import numpy as np 
>>> df = pd.DataFrame(np.arange(25).reshape(5, 5),  
                      index=list('abcde'), 
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a   0   1   2   3   4
b   5   6   7   8   9
c  10  11  12  13  14
d  15  16  17  18  19
e  20  21  22  23  24

然后例如:

>>> df.loc['c': , :'z']  # rows 'c' and onwards AND columns up to 'z'
    x   y   z
c  10  11  12
d  15  16  17
e  20  21  22

>>> df.iloc[:, 3]        # all rows, but only the column at index location 3
a     3
b     8
c    13
d    18
e    23

有时,我们希望混合使用行和列的标签和位置索引方法,以某种方式组合 和 的功能。lociloc

例如,请考虑以下数据帧。如何最好地将行切成“c”并包含“c”取前四列?

>>> import numpy as np 
>>> df = pd.DataFrame(np.arange(25).reshape(5, 5),  
                      index=list('abcde'), 
                      columns=['x','y','z', 8, 9])
>>> df
    x   y   z   8   9
a   0   1   2   3   4
b   5   6   7   8   9
c  10  11  12  13  14
d  15  16  17  18  19
e  20  21  22  23  24

我们可以使用另一种方法和帮助来实现此结果:iloc

>>> df.iloc[:df.index.get_loc('c') + 1, :4]
    x   y   z   8
a   0   1   2   3
b   5   6   7   8
c  10  11  12  13

get_loc() 是一个索引方法,意思是“获取标签在此索引中的位置”。请注意,由于 slicing with 不包含其端点,因此如果还需要行 'c',则必须在此值中添加 1。iloc


答案 2

iloc基于整数定位工作。因此,无论您的行标签是什么,您始终可以通过以下操作获得第一行

df.iloc[0]

或最后五行通过做

df.iloc[-5:]

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

df.iloc[:, 2]    # the : in the first position indicates all rows

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

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

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

df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name'])

然后我们可以通过以下方式获得第一行

df.loc['a']     # equivalent to df.iloc[0]

和列的后两行由'date'

df.loc['b':, 'date']   # equivalent to df.iloc[1:, 1]

等等。现在,可能值得指出的是,a 的默认行和列索引是从 0 开始的整数,在本例中,它们的工作方式相同。这就是为什么你的三个例子是等效的。如果您有非数字索引(如字符串或日期时间),则会引发错误。DataFrameiloclocdf.loc[:5]

此外,您只需使用数据框的:__getitem__

df['time']    # equivalent to df.loc[:, 'time']

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

df.ix[:2, 'time']    # the first two rows of the 'time' column

我认为还值得一提的是,您也可以将布尔向量传递给该方法。例如:loc

 b = [True, False, True]
 df.loc[b] 

将返回 的第 1 行和第 3 行。这等效于用于选择,但它也可用于通过布尔向量进行赋值:dfdf[b]

df.loc[b, 'name'] = 'Mary', 'John'