为什么 Pandas DataFrame 的 [] (__getitem__) 有时选择列,有时选择行?

Hei*_*erg 5 python pandas

鉴于此数据框:

In [40]: df = pd.DataFrame({'A': [1, 1], 'B': [2, 2], 'C': [3, 3]})

In [41]: df
Out[41]:
   A  B  C
0  1  2  3
1  1  2  3
Run Code Online (Sandbox Code Playgroud)

如果我将字符串列表传递给[],它将过滤列:

In [42]: df[['A', 'C']]
Out[42]:
   A  C
0  1  3
1  1  3
Run Code Online (Sandbox Code Playgroud)

但是,如果我将布尔值列表传递给[],它将过滤行:

In [45]: df[[True, False]]
Out[45]:
   A  B  C
0  1  2  3
Run Code Online (Sandbox Code Playgroud)

有没有办法考虑这种差异,而不是“它就是这样”?

And*_*den 1

我的理解是,这复制了 R 的行为,以使迁移 R 脚本更容易,它也ix从不推荐使用的开始。切片的方法有很多,但现在更少了:

  1. 单个项目,获取一列。
  2. 列列表,获取“子框架”
  3. 布尔索引

就我个人而言,我喜欢用于__getitem__所有这些:

In [11]: df[['A', 'C']]
Out[11]:
   A  C
0  1  3
1  1  3

In [12]: df['A']
Out[12]:
0    1
1    1
Name: A, dtype: int64
Run Code Online (Sandbox Code Playgroud)

另一种选择虽然不太含糊(loc(或iloc) ,但过于冗长:

In [13]: df.loc[:, ['A', 'B']]
Out[13]:
   A  B
0  1  2
1  1  2

In [14]: df.loc[:, 'A']
Out[14]:
0    1
1    1
Name: A, dtype: int64
Run Code Online (Sandbox Code Playgroud)

值得注意的是,布尔掩码并不含糊,除非您有一个深奥的示例,其中布尔列和输入长度与 DataFrame 的长度相匹配:

In [21]: df1 = pd.DataFrame({True: [1, 2], False: [3, 4]})

In [22]: df1
Out[22]:
   False  True
0      3      1
1      4      2

In [23]: df1[[True, False]]  # boolean slicing (not as column names)
Out[23]:
   False  True
0      3      1
Run Code Online (Sandbox Code Playgroud)

从历史上看,存在潜在的歧义ix(以及性能问题 - 有很多可能的路径可供选择)。因此,除了消除歧义之外,迁移到lociloc还导致了更快的代码(iloc如果可以的话,通常使用它是最快的)。