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

Sea*_*thy 40 python dataframe pandas

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

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

df_new = df.loc[:, 'col1']
Run Code Online (Sandbox Code Playgroud)

第二种方法 - 看起来更简单,更快捷:

df_new = df['col1']
Run Code Online (Sandbox Code Playgroud)

第三种方法 - 最方便:

df_new = df.col1
Run Code Online (Sandbox Code Playgroud)

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

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

ayh*_*han 43

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

  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行,则假设您有RandeIndex,则会获得行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
Run Code Online (Sandbox Code Playgroud)

这将选择第1行和第2行,然后选择返回对象的列"A"并为其指定值5.问题是,返回的对象可能是一个副本,因此这可能不会更改实际的DataFrame.这引发了 SettingWithCopyWarning.这项任务的正确方法是

df.loc[1:3, 'A'] = 5
Run Code Online (Sandbox Code Playgroud)

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

另请注意,这两个未同时包含在API中..loc之后被添加为更强大和更明确的索引器.有关更多详细信息,请参阅unutbu的答案.


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

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

Fre*_*man 7

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']
Run Code Online (Sandbox Code Playgroud)

但是[],旨在获取具有特定名称的

df['Price']
Run Code Online (Sandbox Code Playgroud)

随着[]您还可以过滤,但它更多的阐述:

df[df['Date'] < datetime.datetime(2010,1,1,7,0,0)]['Price']
Run Code Online (Sandbox Code Playgroud)