【问题标题】:What is the difference between using loc and using just square brackets to filter for columns in Pandas/Python?在 Pandas/Python 中使用 loc 和仅使用方括号过滤列有什么区别?
【发布时间】:2018-07-02 17:02:41
【问题描述】:

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

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

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

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

df_new = df['col1']

第三种方法——最方便:

df_new = df.col1

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

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

【问题讨论】:

  • 或者df.col1呢?对于选择列的非常简单的情况,所有这三个基本上是等效的。 .loc 将让您做的不仅仅是选择一列。 stackoverflow.com/questions/31593201/… 的可能重复项
  • 他们对简单的切片做同样的事情。 loc 更加明确,尤其是当您的列是数字时。
  • 谢谢@juanpa.arrivillaga。好点re:df.col1,这是另一种列选择方法。实际上,我之前已经多次看过另一个问题。它非常适合解释 loc 和 iloc。但是,这个问题是关于另一种方法:“df['col1']”。我只是对为什么有两种(或三种)等效的方法来做看似相同的事情感到困惑。
  • 第三种方法的最大缺点是,当您的列名与现有的 pandas 属性或方法相同时,它会产生歧义。例如。您将列命名为“总和”。那么如果你输入df.sum,会发生什么? (剧透警告,没什么用处,虽然df.sum() 幸运的是仍然有效)所以第三种方式应该被视为很好的捷径,但需要小心
  • 这里有一个不错的解释stackoverflow.com/questions/38886080/…

标签: python pandas dataframe


【解决方案1】:

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

  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,您将获得第 1 行, 2 和 3 假设你有一个RangeIndex。查看详细信息here。)

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

  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

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

另请注意,这两者并未同时包含在 API 中。 .loc 是后来作为更强大和更明确的索引器添加的。详情请参阅unutbu's answer


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

【讨论】:

  • “返回的对象可能是副本”是什么意思?这有点令人困惑。我是否应该期望df[1:3]['A'] = 5 返回的值是副本?
  • @AlessioF 这就是问题所在。我们真的不知道。 pandas 不保证从 df.__getitem__(...) 返回什么,并且在后台,存储数组的内存布局可能会导致视图或副本。通常,当您处理具有单个 dtype 的数据框时,您会得到一个视图,但这并不能保证。我相信他们正在研究一种新方法,而不是使用这些问题的主要来源 BlockManager。
【解决方案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']

【讨论】:

    【解决方案3】:

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

    你可以参考这个问题: Is there a nice way to generate multiple columns using .loc?

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

    【讨论】:

      【解决方案4】:

      如果您对这些方法中的哪一种(至少)是您的用例推荐的方法感到困惑,请查看来自pandas tutorial 的简短说明:

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

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

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

      • 在使用 表格中的位置

      • 您可以为基于loc/iloc 的选择分配新值

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

      【讨论】:

        猜你喜欢
        • 2018-02-20
        • 2012-02-12
        • 2014-04-18
        • 2021-05-12
        • 2015-07-26
        • 1970-01-01
        • 1970-01-01
        • 2016-06-26
        相关资源
        最近更新 更多