在 Pandas/Python 中,使用 loc 和只使用方括号筛选列有什么区别?

我注意到在熊猫数据框架中选择列的三种方法:

使用 loc 选择列的第一种方法:

df_new = df.loc[:, 'col1']

第二种方法似乎更简单、更快捷:

df_new = df['col1']

第三种方法——最方便的:

df_new = df.col1

这三种方法有区别吗?我不这么认为,在这种情况下,我宁愿使用第三种方法。

我最好奇的是为什么有三种方法可以做同样的事情。

36736 次浏览

在下列情况下,它们的行为是一样的:

  1. 选择一个列(df['A']df.loc[:, 'A']-> 选择列 A 相同)
  2. 选择列列表(df[['A', 'B', 'C']]df.loc[:, ['A', 'B', 'C']]-> 相同,选择列 A、 B 和 C)
  3. 按行切片(df[1:3]df.iloc[1:3]-> 相同,选择行1和行2。但是请注意,如果使用 loc而不是 iloc切割行,假设您有一个 RangeIndex,那么您将得到第1、2和3行。详情请参阅 给你。)

然而,[]在以下情况下不起作用:

  1. 您可以使用 df.loc[row_label]选择一行
  2. 可以使用 df.loc[[row_label1, row_label2]]选择行列表
  3. 可以使用 df.loc[:, 'A':'C']对列进行切片

这三个不能用 []来完成。 更重要的是,如果您的选择同时涉及行和列,那么赋值就会成为问题。

df[1:3]['A'] = 5

这将选择第1行和第2行,然后选择返回对象的列“ A”,并将值5赋给它。问题是,返回的对象可能是一个副本,因此这可能不会更改实际的 DataFrame。这提高了 设置拷贝警告。完成这项任务的正确方法是:

df.loc[1:3, 'A'] = 5

使用 .loc,可以保证修改原始 DataFrame。它还允许您切片列(df.loc[:, 'C':'F'])、选择单行(df.loc[5])和选择行列表(df.loc[[1, 2, 5]])。

还要注意的是,这两个并没有同时包含在 API 中。.loc是后来添加的,作为一个更强大、更明确的索引器。有关更多细节,请参见 Unutbu 的回答


注意: 使用 [].获取列是完全不同的主题。.的存在只是为了方便。它只允许访问名称为有效 Python 标识符的列(即,它们不能包含空格,它们不能由数字组成...)。当名称与 Series/DataFrame 方法冲突时,不能使用它。它也不能用于不存在的列(也就是说,如果没有列 a,赋值 df.a = 1将无法工作)。除此之外,.[]是相同的。

当索引不是数字的时候(例如 DatetimeIndex) ,loc特别有用,因为你可以从索引中获得带有特定标签的 一排排:

df.loc['2010-05-04 07:00:00']
df.loc['2010-1-1 0:00:00':'2010-12-31 23:59:59 ','Price']

然而,[]的目的是获得具有特定名称的 柱子:

df['Price']

使用 []你也可以过滤 一排排,但是它更加详细:

df[df['Date'] < datetime.datetime(2010,1,1,7,0,0)]['Price']

在创建具有多个列的数据框时,df.loc []和 df []之间似乎有所不同。

你可以参考这个问题: 有没有一种很好的方法来使用. loc 生成多个列?

在这里,您不能使用 df.loc[:,['name1','name2']]生成多列,但是您可以使用双括号 df[['name1','name2']]。(我想知道为什么他们的行为会有所不同。)

如果您对这些方法中的哪一种(至少)是您的用例推荐的方法感到困惑,请看一下 熊猫教程中的简短说明:

  • 选择数据子集时,使用方括号 []

  • 在这些括号中,您可以使用一个列/行标签,即一个列表 列/行标签、一片标签、条件表达式或 结肠。

  • 在使用行和 列名

  • 方法时,使用 iloc选择特定的行和/或列 在桌子上的位置

  • 你可以根据 loc/iloc选择 赋予新的价值

我强调了其中的一些要点,以使它们的用例差异更加清晰。