ChatGPT解决这个技术问题 Extra ChatGPT

iloc 和 loc 有何不同?

有人能解释一下这两种切片方法有何不同吗?
我看过 the docs,也看过 these answers,但我仍然无法理解这三种方法有何不同。对我来说,它们在很大程度上似乎可以互换,因为它们处于较低的切片级别。

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

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

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

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

提到 SettingWithCopyWarning 场景非常重要:stackoverflow.com/questions/20625582/…stackoverflow.com/questions/23688307/…
请注意,现在计划弃用 ix:github.com/pandas-dev/pandas/issues/14218

P
Parham

标签与位置

这两种方法的主要区别是:

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[] s.iloc[] 0 单个项目 索引标签 0 处的值(字符串 'd') 索引位置 0 处的值(字符串 'a')0:1切片 两行(标签 0 和 1) 一行(位置 0 的第一行) 1:47 切片,越界结束 零行(空系列) 五行(从位置 1 开始) 1:47:-1 切片负步三行(标签 1 到 47) 零行(空系列) [2, 0] 整数列表 具有给定标签的两行 具有给定位置的两行 s > 'e' 布尔系列(指示哪些值具有属性) 一行(包含 'f') NotImplementedError (s>'e').values Bool 数组 一行(包含 'f') 与 loc 相同 999 int object not in index KeyError IndexError (out of bounds) -1 int object not in index 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

由于 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。


很好的解释!我一直有一个相关的问题是 loc、iloc 和 ix 与 SettingWithCopy 警告有什么关系(如果有的话)?有一些文档,但老实说我还是有点困惑pandas.pydata.org/pandas-docs/stable/…
@measureallthethings:如果将 locilocix 链接在一起,它们仍可能会触发警告。使用链接文档 dfmi.loc[:, 'one'].loc[:, 'second'] 中的示例 DataFrame 会像 dfmi['one']['second'] 一样触发警告,因为第一个索引操作可能会返回数据的副本(而不是视图)。
如果你想用 Date 或 df.ix[date, 'Cash'] 之类的东西来查找 DateIndex,你会使用什么?
@cjm2671:在这种情况下,locix 都应该工作。例如,df.loc['2016-04-29', 'Cash'] 将返回“现金”列中具有该特定日期的所有行索引。 (在检索带有字符串的索引时,您可以根据自己的喜好指定具体的内容,例如 '2016-01' 将选择 2016 年 1 月的所有日期时间,“2016-01-02 11”将选择 2016 年 1 月 2 日的日期时间,时间为 11:?? :??.)
如果您想在某个时候更新此答案,这里有关于如何使用 loc/iloc 而不是 ix github.com/pandas-dev/pandas/issues/14218 的建议
n
nbro

iloc 基于整数定位工作。所以无论你的行标签是什么,你总是可以,例如,通过做得到第一行

df.iloc[0]

或最后五行做

df.iloc[-5:]

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

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 的第 1 行和第 3 行。这等效于 df[b] 进行选择,但它也可以用于通过布尔向量进行分配:

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

df.iloc[:, :] 是否等同于所有行和列?
就像 df.loc[:, :] 一样。它可用于重新分配整个 DataFrame 的值或创建它的视图。
嗨,您知道为什么 loc 和 iloc 在方括号 [ ] 之间使用参数,而不是在经典括号 ( ) 之间作为常规方法吗?
@MarineGalantin,因为它们指示索引和切片操作,而不是标准方法。您正在选择数据子集。
T
Ted Petrou

在我看来,接受的答案令人困惑,因为它使用只有缺失值的 DataFrame。我也不喜欢 .ilocposition-based 一词,而是更喜欢 integer location,因为它更具描述性,并且正是 .iloc 所代表的含义。关键字是 INTEGER - .iloc 需要 INTEGERS。

有关更多信息,请参阅我关于子集选择的极其详细的 blog series

.ix 已弃用且模棱两可,永远不应使用

由于不推荐使用 .ix,我们将只关注 .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'])

https://i.stack.imgur.com/4VsqO.png

粗体中的所有单词都是标签。标签 agecolorfoodheightscorestate 用于 。其他标签 JaneNickAaronPenelopeDeanChristinaCornelia 用于 索引

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

.loc 仅按标签选择数据

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

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

一个字符串

字符串列表

使用字符串作为开始和结束值的切片表示法

使用带有字符串的 .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,其中的行按列表中指定的顺序排列:

https://i.stack.imgur.com/ST3Q2.png

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

切片符号由开始、停止和步长值定义。当按标签切片时,pandas 在返回值中包含停止值。以下切片从 Aaron 到 Dean,包括在内。它的步长没有明确定义,但默认为 1。

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

https://i.stack.imgur.com/XXSJ4.png

可以以与 Python 列表相同的方式获取复杂切片。

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

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

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

一个整数

整数列表

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

使用带有整数的 .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:

https://i.stack.imgur.com/g7WZx.png

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

df.iloc[:5:3]

https://i.stack.imgur.com/w6vGg.png

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

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

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

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

https://i.stack.imgur.com/RVFe3.png

这对行使用标签列表,对列使用切片表示法

我们自然可以只使用整数对 .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]

https://i.stack.imgur.com/5f8Y8.png

索引运算符 [] 也可以选择行和列,但不能同时选择。

大多数人都熟悉 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']]

https://i.stack.imgur.com/t1p1V.png

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

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

https://i.stack.imgur.com/GSWT1.png

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

https://i.stack.imgur.com/lX1Wj.png

.loc/.iloc 用于选择行的明确性是非常受欢迎的。单独的索引运算符无法同时选择行和列。

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

哇,这是我在编程主题中遇到的非常清晰和清晰的解释之一,您在最后解释的关于在行或列上工作的正常索引是我们拥有 loc 和 iloc 的原因之一方法。我在数据营课程中遇到了这个警告。 a.) df.columns 和 df.index 返回什么?它是一个字符串列表吗?如果是列表,是否允许在列表中访问像 df.columns[ [2,4] ] 这样的两个元素? b.) 我可以在 df.columns 上调用 get_loc() 吗? c.) 为什么我们需要在 iloc 的情况下调用 df['age']>30.values。
这是一个非常好的答案,我喜欢它并没有深入到 ix 中,这已被弃用并且深入研究毫无意义。谢谢。
比目前接受的最高答案更有意义。
为什么他们使用 loc 而不是 label?似乎命名法基本上是一个混淆生成器。
l
lmiguelvargasf

.loc.iloc 用于索引,即提取部分数据。本质上,区别在于 .loc 允许基于标签的索引,而 .iloc 允许基于位置的索引。

如果您对 .loc.iloc 感到困惑,请记住 .iloc 是基于索引(以 i 开头)位置,而 .loc 是基于标签(开始l)。

.loc

.loc 应该基于索引标签而不是位置,因此它类似于 Python 基于字典的索引。但是,它可以接受布尔数组、切片和标签列表(这些都不适用于 Python 字典)。

国际劳工组织

.iloc 根据索引位置进行查找,即 pandas 的行为类似于 Python 列表。如果该位置没有索引,pandas 将引发 IndexError

例子

以下示例用于说明 .iloc.loc 之间的区别。让我们考虑以下系列:

>>> s = pd.Series([11, 9], index=["1990", "1993"], name="Magic Numbers")
>>> s
1990    11
1993     9
Name: Magic Numbers , dtype: int64

.iloc 示例

>>> s.iloc[0]
11
>>> s.iloc[-1]
9
>>> s.iloc[4]
Traceback (most recent call last):
    ...
IndexError: single positional indexer is out-of-bounds
>>> s.iloc[0:3] # slice
1990 11
1993  9
Name: Magic Numbers , dtype: int64
>>> s.iloc[[0,1]] # list
1990 11
1993  9
Name: Magic Numbers , dtype: int64

.loc 示例

>>> s.loc['1990']
11
>>> s.loc['1970']
Traceback (most recent call last):
    ...
KeyError: ’the label [1970] is not in the [index]’
>>> mask = s > 9
>>> s.loc[mask]
1990 11
Name: Magic Numbers , dtype: int64
>>> s.loc['1990':] # slice
1990    11
1993     9
Name: Magic Numbers, dtype: int64

因为 s 具有字符串索引值,所以使用整数索引时 .loc 将失败:

>>> s.loc[0]
Traceback (most recent call last):
    ...
KeyError: 0

b
buhtz

DataFrame.loc() : 按索引值选择行

DataFrame.iloc() : 按行数选择行

例子:

选择表的前 5 行,df1 是您的数据框

df1.iloc[:5]

选择表的前 A、B 行,df1 是您的数据框

df1.loc['A','B']

T
TanuAD

这个例子将说明差异:

df = pd.DataFrame({'col1': [1,2,3,4,5], 'col2': ["foo", "bar", "baz", "foobar", "foobaz"]})
  col1  col2
0   1   foo
1   2   bar
2   3   baz
3   4   foobar
4   5   foobaz

df = df.sort_values('col1', ascending = False)
      col1  col2
    4   5   foobaz
    3   4   foobar
    2   3   baz
    1   2   bar
    0   1   foo

基于索引的访问:

df.iloc[0, 0:2]
col1         5
col2    foobaz
Name: 4, dtype: object

我们得到排序后的数据帧的第一行。 (这不是索引为 0 的行,而是索引为 4 的行)。

基于位置的访问:

df.loc[0, 'col1':'col2']
col1      1
col2    foo
Name: 0, dtype: object

即使对 df 进行排序,我们也会得到索引为 0 的行。