iloc 和 loc 有何不同?

新手上路,请多包涵

有人可以解释这两种切片方法有何不同吗?

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

例如,假设我们想要获取 a DataFrame 的前五行。这两个是如何工作的?

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

有人可以提出三种使用区别更清楚的情况吗?


曾几何时,我也想知道这两个函数与 df.ix[:5] 但是 ix 已从 pandas 1.0 中删除,所以我不再关心了。

原文由 AZhao 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 527
2 个回答

标签 位置

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

  • 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带负步的切片三行(标签 1 回到 47 行(空系列)[2, 0]整数列表具有给定标签的 行具有给定位置的 s > 'e' Bool系列(表示哪些值具有该属性) 排(包含 'f'NotImplementedError(s>'e').values布尔数组 排(包含 'f' )与 loc 相同999 int 对象不在索引中KeyErrorIndexError (越界)-1 int 对象不在索引中KeyError返回最后一个值 slambda 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

由于 loc 是基于标签的,它可以使用 s2.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

行和列

lociloc 使用 DataFrame 的方式与使用 Series 的方式相同。值得注意的是,这两种方法都可以同时处理列和行。

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

考虑下面定义的 DataFrame:

 >>> 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 的功能。

例如,考虑以下 DataFrame。如何最好地将包含“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() 是一个索引方法,意思是“获取标签在这个索引中的位置”。请注意,由于使用 iloc 进行切片不包括其端点,因此如果我们也需要行“c”,则必须将此值加 1。

原文由 Alex Riley 发布,翻译遵循 CC BY-SA 4.0 许可协议

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]

等等。现在,可能值得指出的是 DataFrame 的默认行和列索引是从 0 开始的整数,在这种情况下 ilocloc 可以工作同样的方式。这就是为什么你的三个例子是等价的。 如果您有一个非数字索引,例如字符串或日期时间, df.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]

将返回 df 的第一行和第三行。这相当于 df[b] 用于选择,但它也可用于通过布尔向量进行分配:

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

原文由 JoeCondron 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题