在 Pandas/Python 中使用 loc 和仅使用方括号过滤列有什么区别?

What is the difference between using loc and using just square brackets to filter for columns in Pandas/Python?

提问人:Sean McCarthy 提问时间:1/24/2018 最后编辑:Mad PhysicistSean McCarthy 更新时间:11/12/2021 访问量:47155

问:

我注意到在 Pandas DataFrame 中选择列的三种方法:

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

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

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

df_new = df['col1']

第三种方法 - 最方便:

df_new = df.col1

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

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

Python Pandas 数据帧

评论

2赞 juanpa.arrivillaga 1/24/2018
或者呢?对于选择列的非常简单的情况,这三者基本上都是等价的。 将让您执行比选择列更多操作的功能。stackoverflow.com/questions/31593201/ 的可能重复...df.col1.loc
1赞 Gabriel A 1/24/2018
它们对简单的切片做同样的事情。loc 更明确,尤其是当您的列是数字时。
0赞 Sean McCarthy 1/24/2018
谢谢@juanpa.arrivillaga。好点:df.col1,这是另一种列选择方法。实际上,我之前已经看过另一个问题好几次了。它非常适合解释 loc 和 iloc。但是,这个问题是关于另一种方法的:“df['col1']”。我只是对为什么有两种(或三种)等效的方法来做看似相同的事情感到困惑。
1赞 JohnE 1/24/2018
第三种方法的最大缺点是,当您的列名与现有的 pandas 属性或方法相同时,它是模棱两可的。例如,您将一列命名为“sum”。那么,如果键入 ,会发生什么?(剧透警报,没什么用,尽管幸运的是仍然有效)因此,第三种方式应该被视为一种捷径,这很好,但需要小心df.sumdf.sum()
1赞 Gaurav Taneja 1/24/2018
这里有一个体面的解释 stackoverflow.com/questions/38886080/......

答:

171赞 ayhan 1/24/2018 #1

在以下情况下,它们的行为相同:

  1. 选择单个列(与 -> 选择 A 列相同)df['A']df.loc[:, 'A']
  2. 选择列列表(与 -> 选择列 A、B 和 C 相同)df[['A', 'B', 'C']]df.loc[:, ['A', 'B', 'C']]
  3. 按行切片 ( 与 -> 选择第 1 行和第 2 行相同。但是请注意,如果使用 ,而不是 ,则将获得第 1、2 和 3 行(假设您有 RangeIndex)。详情请见此处df[1:3]df.iloc[1:3]lociloc

但是,在以下情况下不起作用:[]

  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。这将引发 SettingWithCopyWarning。进行此分配的正确方法是:

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

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

另请注意,这两个没有同时包含在 API 中。 很久以后才添加为更强大、更显式的索引器。有关更多详细信息,请参阅 unutbu 的回答.loc


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

评论

3赞 AlessioF 7/22/2021
“返回对象可能是副本”是什么意思?这有点令人困惑。我是否应该期望返回的值是副本?df[1:3]['A'] = 5
4赞 ayhan 7/23/2021
@AlessioF 这就是问题所在。我们真的不知道。pandas 不保证从 返回什么,在后台,存储数组的内存布局可能会导致视图或副本。通常,当您使用单个 dtype 处理数据帧时,您会获得一个视图,但这并不能保证。我相信他们正在研究一种新方法,而不是使用 BlockManager,这是这些问题的主要来源。df.__getitem__(...)
0赞 skan 8/4/2023
当找不到选择时,df.loc[] 会失败。
12赞 Freeman 10/22/2018 #2

loc当索引不是数字(例如 DatetimeIndex)时特别有用,因为您可以从索引中获取具有特定标签的行

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']
0赞 Matthew Son 2/20/2019 #3

当您创建具有多个列的 DataFrame 时,df.loc[] 和 df[] 之间似乎存在差异。

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

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

评论

0赞 Mario 3/16/2023
当我尝试时,这两种方法都有效,至少在最后一个 Pandas 版本 (1.5.3) 中是这样。看截图
3赞 Pedram Parsian 11/12/2021 #4

如果您对以下哪种方法(至少)是您的用例推荐的方法感到困惑,请查看 pandas 教程中的简要说明:

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

  • 在这些括号内,您可以使用单个列/行标签,即列表 列/行标签、标签切片、条件表达式或 冒号。

  • 选择特定的行和/或列,使用行和 列名loc

  • 选择特定的行和/或列,使用 表中的位置iloc

  • 您可以根据 / 为所选内容分配新值lociloc

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

评论

0赞 skan 8/4/2023
如果您需要混合方法、位置和名称,例如列“A”的第一行,该怎么办?