Pandas中双括号`[[...]]`和单括号`[..]`索引的区别

32

我对以下代码行的语法感到困惑:

x_values = dataframe[['Brains']]

数据框对象由2列组成(Brains和Bodies)

Brains Bodies
42     34
32     23

当我打印x_values时,我得到了类似这样的结果:

Brains
0  42
1  32

我已经了解了有关数据框对象的属性和方法的Pandas文档,但双括号语法让我感到困惑。


我了解数据框对象的属性和方法,但是双括号语法令我感到困惑。
4个回答

38

想一想:

源数据框 DF:

In [79]: df
Out[79]:
   Brains  Bodies
0      42      34
1      32      23

选择一列 - 在Pandas.Series中产生结果:

In [80]: df['Brains']
Out[80]:
0    42
1    32
Name: Brains, dtype: int64

In [81]: type(df['Brains'])
Out[81]: pandas.core.series.Series

选择数据框的子集 - 将生成一个新的数据框:

In [82]: df[['Brains']]
Out[82]:
   Brains
0      42
1      32

In [83]: type(df[['Brains']])
Out[83]: pandas.core.frame.DataFrame

结论: 第二种方法允许我们从数据框中选择多列。第一种方法只能选择单列...

演示:

In [84]: df = pd.DataFrame(np.random.rand(5,6), columns=list('abcdef'))

In [85]: df
Out[85]:
          a         b         c         d         e         f
0  0.065196  0.257422  0.273534  0.831993  0.487693  0.660252
1  0.641677  0.462979  0.207757  0.597599  0.117029  0.429324
2  0.345314  0.053551  0.634602  0.143417  0.946373  0.770590
3  0.860276  0.223166  0.001615  0.212880  0.907163  0.437295
4  0.670969  0.218909  0.382810  0.275696  0.012626  0.347549

In [86]: df[['e','a','c']]
Out[86]:
          e         a         c
0  0.487693  0.065196  0.273534
1  0.117029  0.641677  0.207757
2  0.946373  0.345314  0.634602
3  0.907163  0.860276  0.001615
4  0.012626  0.670969  0.382810

如果我们在列表中只指定一列,那么将会得到一个只有一列的DataFrame:

In [87]: df[['e']]
Out[87]:
          e
0  0.487693
1  0.117029
2  0.946373
3  0.907163
4  0.012626

16
为了消除任何可能的混淆,第一种形式相当于 column = 'Brains'; df[column],第二种形式相当于 subset = ['Brains']; df[subset]。 第一种形式传递一个字符串,第二种形式传递一个列表。 并不是使用[[]]会执行特殊的索引方式,而是传递的对象类型不同。 - SethMMorton
@MikeFellner,请查看SethMMorton的评论。 - MaxU - stand with Ukraine
@SethMMorton,我认为你应该把你的评论变成一个答案——它绝对值得的 :) - MaxU - stand with Ukraine
1
我已经将评论变成答案,因为似乎有两件事让OP感到困惑。 - SethMMorton
1
简单来说,如果索引是一个数组,它将返回具有匹配列的DataFrame,否则它将返回一个具有单个匹配列的系列。 - dzieciou
显示剩余2条评论

23

在Python中,[[]]没有特殊的语法。相反,一个列表被创建,然后将该列表作为参数传递给DataFrame索引函数。

根据@MaxU的答案,如果将单个字符串传递给DataFrame,则返回表示该列的Series。如果传递一个字符串列表,则返回包含给定列的DataFrame。

因此,当您执行以下操作时:

# Print "Brains" column as Series
print(df['Brains'])
# Return a DataFrame with only one column called "Brains"
print(df[['Brains']])

它等同于以下内容

# Print "Brains" column as Series
column_to_get = 'Brains'
print(df[column_to_get])
# Return a DataFrame with only one column called "Brains"
subset_of_columns_to_get = ['Brains']
print(df[subset_of_columns_to_get])

在这两种情况下,DataFrame 都是使用 [] 运算符进行索引的。

Python 使用 [] 运算符既用于索引也用于构建列表文字,我相信这最终是您困惑的原因。在 df[['Brains']] 中,外部的 [] 执行索引操作,内部创建一个列表。

>>> some_list = ['Brains']
>>> some_list_of_lists = [['Brains']]
>>> ['Brains'] == [['Brains']][0]
True
>>> 'Brains' == [['Brains']][0][0] == [['Brains'][0]][0]
True

上面的例子说明了Python在任何时候都不会特殊地看待[[,并对其进行解释。在最后一个复杂的例子([['Brains'][0]][0])中,没有特殊的][运算符或]][运算符...... 发生的是:

  • 创建一个单元素列表(['Brains'])
  • 索引该列表的第一个元素(['Brains'][0] => 'Brains')
  • 将其放入另一个列表中([['Brains'][0]] => ['Brains'])
  • 然后索引该列表的第一个元素([['Brains'][0]][0] => 'Brains')

3
这应该是被采纳的答案。我也曾经对语法非常困惑,但现在我明白了双重 [[]] 简单地等同于两个 []。例如,df[df['col']==val] 返回一个数据框而不是一个系列,因为 df['col']==val 是一个系列,结果是一个系列的系列,也就是一个数据框。 - tartaruga_casco_mole
是的,这个答案是最好的。它澄清了一些我(以及大多数人)忽略的显而易见的事情。[['Brains']][0][0][0]访问字符串'Brains'中的'B'。[['Brains']][0][0]访问字符串'Brains'。[['Brains']][0]从单元素列表[['Brains']]中访问第一个(也是唯一的)列表['Brains']。如果这是一个多元素列表[['Brains'],['Bodies'],['Souls']],那么访问运算符可以钻入任何三个列表中的任何一个。[['Brains'],['Bodies'],['Souls']][2][0][0]访问列表3中的'S'。[['Brains'],['Bodies'],['Souls']][0] = ['Brains']。 - Rich Lysakowski PhD
很棒的插图!谢谢。 - Harikrishnan Balachandran

1

其他解决方案展示了Series和DataFrame之间的区别。对于数学思维者,您可能希望考虑输入和输出的维度。以下是摘要:

Object                                Series          DataFrame
Dimensions (obj.ndim)                      1                  2
Syntax arg dim                             0                  1
Syntax                             df['col']        df[['col']]
Max indexing dim                           1                  2
Label indexing              df['col'].loc[x]   df.loc[x, 'col']
Label indexing (scalar)      df['col'].at[x]    df.at[x, 'col']
Integer indexing           df['col'].iloc[x]  df.iloc[x, 'col']
Integer indexing (scalar)   df['col'].iat[x]   dfi.at[x, 'col']

当您在pd.DataFrame.__getitem__中指定标量或列表参数时,其中[]是语法糖,您的参数维数比结果的维数小一个。因此,标量(0维)给出1维系列。列表(1维)给出2维数据框。这是有道理的,因为额外的维度是数据框索引,即行。即使您的数据框没有行,这也是适用的情况。

0

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接