Pandas中的Iloc与Loc:带示例的指南

我们在学习Pandas时,最让人困惑的事情之一就是 .loc.iloc 之间的区别。

让我们结束这种困惑,澄清这两种方法之间的差异。我将提供大量示例,希望到这篇博客结束时,区别会更加清晰。

在Pandas中,什么是 .loc 和 .iloc?

.loc.iloc 都是Pandas DataFrame的重要属性,均用于选择特定的数据子集。它们的目的是访问并能够操作DataFrame的特定部分,而不是整个DataFrame。

特性

.loc

.iloc

语法

df.loc[row_indexer, column_indexer]

df.iloc[row_indexer, column_indexer]

索引方法

基于标签的索引

基于位置的索引

用于参考

行和列标签(名称)

行和列的数字索引(从0开始)

从表中可以看出,语法看起来非常相似。不同之处在于如何使用row_indexercolumn_indexer参数。这是因为这两种方法提供了不同的数据索引方式:而.loc基于标签名称进行索引,.iloc则将行和列的数字位置索引作为参数。

让我们逐一详细研究这两种方法,从.loc开始。

使用.loc:按标签进行选择

为了说明这些概念,让我们考虑一个由这个名为df的DataFrame表示的假想客户数据库,其中Customer ID表示行索引:

Customer ID

姓名

国家

地区

年龄

C123

约翰·多

美国

北美洲

67

C234

佩特拉·穆勒

德国

欧洲

51

C345

Ali Khan

Pakistan

Asia

19

C456

Maria Gonzalez

Mexico

North America

26

C567

David Lee

China

Asia

40

有四种使用.loc选择行的主要方法:

  • 选择单行
  • 选择多个行
  • 选择行的切片
  • 条件行选择

使用 .loc 选择单行

要选择单行,我们使用要检索的行的标签作为 row_indexer。因此,语法如下: df.loc['row_label']。让我们用这个来显示我们客户 Ali Khan 的所有信息:

df.loc['C345']

C345

 

姓名

阿里·汗

国家

巴基斯坦

地区

亚洲

年龄

19

使用.loc选择多行

如果我们想选择不一定按顺序排列的多行,我们必须将它们的行标签列表作为row_indexer参数传递。这意味着我们需要使用不止一对而是两对方括号:一对用于常规.loc语法,另一对用于标签列表。

代码df.loc[['row_label_1', 'row_label_2']]将返回指定列表中的df数据框的两行。假设我们想知道的不仅是Ali Khan的信息,还包括David Lee的信息:

df.loc[['C345', 'C567']]

客户ID

姓名

国家

地区

年龄

C345

阿里·汗

巴基斯坦

亚洲

19

C567

大卫·李

中国

亚洲

40

使用.loc选择行的一部分

我们可以通过传递第一个和最后一个行标签并用冒号分隔来选择一系列行:df.loc['row_label_start':'row_label_end']。我们可以这样显示数据框的前四行:

df.loc['C123' : 'C456']

客户ID

姓名

国家

地区

注册日期

C123

约翰·杜

美国

北美洲

67

C234

彼得拉·穆勒

德国

欧洲

51

C345

阿里·汗

巴基斯坦

亚洲

19

C456

玛丽亚·冈萨雷斯

墨西哥

北美洲

26

这里有两件事需要记住:

  1. 输出包括在row_label_end中指定的行。这与.iloc不同,我们稍后会讨论。
  2. 我们只使用一对方括号,尽管我们想检索多行。我们不使用列表来指定各行,因此使用两个方括号将返回SyntaxError

使用.loc进行条件选择行

我们还可以根据条件表达式返回行。我们可以通过是否满足某个条件来过滤所有行,仅显示满足条件的行。

对应的语法是df.loc[conditional_expression],其中conditional_expression是关于特定列中允许值的语句。

对于包含非数字数据的列(如 姓名国家),该语句只能使用等于或不等于运算符,因为值之间没有顺序。例如,我们可以返回所有不来自亚洲的客户的行:

df.loc[df['Region'] != 'Asia']

客户ID

姓名

国家

地区

年龄

C123

约翰·多

美国

北美

67

C234

彼得拉·穆勒

德国

欧洲

51

C456

玛利亚·冈萨雷斯

墨西哥

北美洲

26

使用 .loc 选择单列

要选择列,我们需要指定 column_indexer 参数,该参数在 row_indexer 参数之后。如果我们只想指定 column_indexer,我们需要以某种方式标记我们想要返回所有行并仅对列进行过滤。让我们看看如何做到这一点!

选择单列可以通过指定相应列的 column_indexer 来完成。要检索所有行,我们需要使用简单的冒号指定 row_indexer。我们得到了一个看起来像这样语法: df.loc[:, 'column_name'].

让我们显示每位客户的 姓名

df.loc[:, 'Name']

客户ID

姓名

C123

约翰·杜

C234

彼特拉·穆勒

C345

阿里·汗

C456

玛丽亚·冈萨雷斯

C567

大卫·李

使用.loc选择多列

与选择多行类似,如果我们想要返回数据框中不一定按顺序排列的多列,我们需要传递一个列标签的列表:df.loc[:, [col_label_1, 'col_label_2']]

假设我们想要将所有客户的年龄添加到我们的最终输出中,可以这样操作:

df.loc[:, ['Name', 'Age']]

客户ID

姓名

年龄

C123

约翰·杜

67

C234

彼特拉·穆勒

51

C345

Ali Khan

19

C456

Maria Gonzalez

26

C567

David Lee

40

使用.loc选择列的切片

在两个指定列标签之间使用冒号将选择这两列之间的所有列。它包括最后一列,这意味着列名为col_end也会在标准语法中被选择,即:df.loc[:, 'col_start':'col_end']

如果我们对客户的姓名国家地区感兴趣,我们的代码行可以是:

df.loc[:, 'Name':'Region']

客户ID

姓名

国家

地区

C123

约翰·道

美国

北美洲

C234

佩特拉·穆勒

德国

欧洲

C345

阿里·汗

巴基斯坦

亚洲

C456

玛丽亚·冈萨雷斯

墨西哥

北美洲

C567

大卫·李

中国

亚洲

结合行和列的选择使用 .loc

也可以同时指定 row_indexercolumn_indexer。这可以用来检索单个信息,即来自 DataFrame 的一个单元格。为此,我们使用语法 df.loc['row_label', 'column_name'] 指定一行和一列。

更有用的情况是返回一个子 DataFrame,专注于我们感兴趣的行和列集合。可以使用方括号将两个索引器指定为列表,或使用冒号指定为切片,甚至可以结合条件表达式进行行选择。

以下是一个示例,返回每位年龄超过 30 岁的客户的 NameCountryRegion

df.loc[df['Age'] > 30, 'Name':'Region']

客户 ID

姓名

国家

地区

C123

约翰·多

美国

北美

C234

佩特拉·穆勒

德国

欧洲

C567

大卫·李

中国

亚洲

使用 .iloc:按整数位置选择

.iloc按位置而不是标签选择。这是使用 .iloc 的标准语法:df.iloc[row_indexer, column_indexer]。需要注意两件特别的事情:

  • 从 0 开始计数:第一行和第一列的索引是 0,第二个是 1,依此类推。
  • 范围结束值的排他性:使用切片时,冒号后指定的行或列不包括在选择中。

使用 .iloc 选择单行

可以使用表示行索引号的整数作为 row_indexer 选择单行。我们不需要引号,因为我们输入的是整数而不是标签字符串,正如我们使用 .loc 时那样。要返回名为 df 的 DataFrame 的第一行,输入 df.iloc[0]

在我们的示例 DataFrame 中,这一行代码返回约翰·多的信息:

df.iloc[0]

C123

 

姓名

约翰·多

国家

美国

地区

北美

年龄

67

使用 .iloc 选择多行

使用 .iloc 选择多行的方式与 .loc 相同——我们在一个带方括号的列表中输入行索引整数。语法如下: df.iloc[[0, 3, 4]]

在我们的客户表中可以看到相应的输出如下:

df.iloc[[0, 3, 4]]

客户ID

姓名

国家

地区

年龄

C123

约翰·多

美国

北美洲

67

C456

玛丽亚·冈萨雷斯

墨西哥

北美洲

26

C567

大卫·李

中国

亚洲

40

使用 .iloc 选择行切片

要选择一段行,我们在两个指定的行索引整数之间使用冒号。现在,我们必须注意前面提到的排他性。

我们可以将 df.iloc[1:4] 这一行作为例子来说明这个概念。索引号 1 意味着第二行,因此我们的切片从这里开始。索引整数 4 代表第五行——但由于 .iloc 在切片选择中不包括最后一个,因此我们的输出将包括所有行,直到这一行之前的最后一行。因此,它将返回第二、第三和第四行。

让我们证明这一行的效果是正确的:

df.iloc[1:4]

客户ID

姓名

国家

地区

年龄

C234

佩特拉·穆勒

德国

欧洲

51

C345

阿里·汗

巴基斯坦

亚洲

19

C456

玛利亚·冈萨雷斯

墨西哥

北美

26

选择单列使用.iloc

使用.iloc选择列的逻辑遵循我们迄今为止学到的内容。让我们看看如何对单个列、多个列和列切片进行操作。

就像使用.loc一样,重要的是在继续进行column_indexer之前指定row_indexer。要检索df的第三列的每一行的值,我们输入df.iloc[:, 2]

因为Region是我们DataFrame中的第三列,所以它将作为该行代码的结果被检索出来:

df.iloc[:, 2]

Customer ID

Region

C123

North America

C234

Europe

C345

Asia

C456

North America

C567

Asia

使用 .iloc 选择多个列

要选择不一定是连续的多个列,我们可以再次输入一个包含整数的列表作为 column_indexer。代码 df.iloc[:, [0, 3]] 返回第一列和第四列。

在我们的例子中,显示的信息是每位客户的 姓名年龄

df.iloc[:, [0, 3]]

客户ID

姓名

年龄

C123

约翰·多

67

C234

佩特拉·穆勒

51

C345

阿里·汗

19

C456

玛利亚·冈萨雷斯

26

C567

大卫·李

40

使用 .iloc 选择列的切片

使用 .iloc 进行切片选择时,column_indexer 的逻辑与 row_indexer 相同。冒号后的整数所代表的列不包含在输出中。要检索第二和第三列,代码行应如下所示:df.iloc[:, 1:3]

下面这行代码返回我们关于客户的所有地理信息:

df.iloc[:, 1:3]

客户ID

国家

地区

C123

美国

北美

C234

德国

欧洲

C345

巴基斯坦

亚洲

C456

墨西哥

北美洲

C567

中国

亚洲

使用 .iloc 进行行列组合选择

我们可以将关于 .iloc 的学习结合起来,以组合行和列的选择。同样,可以返回单个单元格或子数据框。要返回行 3 和列 4 的交集单元格,我们输入 df.iloc[2, 3]

就像使用 .loc 一样,我们可以使用方括号将两个索引器指定为列表,或使用冒号指定为切片。如果我们想使用条件表达式选择行,技术上使用 .iloc 也是可能的,但不推荐。使用标签名称和 .loc 通常更直观且不易出错。

这个最后的例子显示了我们数据框中第一、第二和第五行的 国家地区年龄

df.iloc[[0,1,4], 1:4]

客户ID

国家

地区

年龄

C123

美国

北美洲

67

C234

德国

欧洲

51

C567

中国

亚洲

40

.iloc vs .loc:何时使用哪个

通常,有一个简单的经验法则,方法的选择取决于您对数据框的了解程度:

  • 当您知道行/列的标签(名称)时,请使用 .loc
  • 当您知道行/列的整数位置时,请使用.iloc

某些情况下,根据其性质会更倾向于使用.loc.iloc。例如,使用整数迭代行或列比使用标签更容易和直观。正如我们已经提到的,基于列值条件过滤行时,使用列标签名称更不容易出错。

偏向于使用.loc的情况

偏向于使用.iloc的情况

您的DataFrame具有有意义的索引/列名称。

您正在按照它们的位置迭代行/列。

您需要根据列值的条件进行筛选。

索引/列名称与您的任务无关。

使用.loc和.iloc时的KeyError、NameError和Index Error

让我们看看可能出现的问题。在使用.loc时的一个常见问题是遇到KeyError。当我们尝试访问不存在于DataFrame中的行或列标签时会出现此错误。为了避免这种情况,我们必须始终确保我们使用的标签是准确的,并且它们与DataFrame中现有的标签匹配,并且要仔细检查是否存在拼写错误。

此外,始终使用引号括起使用.loc指定的标签非常重要。忘记引号将导致NameError

当使用 .iloc 时,如果我们指定的整数位置超出了 DataFrame 索引的有效范围,就会发生 IndexError。当您尝试访问的索引不存在时,就会发生这种情况,可能是因为它超出了 DataFrame 的行数或列数,或者因为它是一个负值。为防止此错误,请检查 DataFrame 的维度,并在有效范围内使用适当的索引值。

结论

我希望这篇博客对您有所帮助,并且现在您对 .loc.iloc 之间的区别有了清晰的认识。要了解更多,以下是一些好的后续步骤:

Source:
https://www.datacamp.com/tutorial/loc-vs-iloc