为什么 Pandas MultiIndex 切片在选择第一个索引级别的所有值时需要列占位符?

问题描述 投票:0回答:1

考虑这个带有 MultiIndex 的 Pandas 数据框:

df = pd.DataFrame({'x': [1, 2, 3, 4]})
arrays = [[1, 1, 2, 2], [False, True, False, True]]
df.index = pd.MultiIndex.from_arrays(arrays, names=('grp', 'is_even'))

df
             x
grp is_even   
1   False    1
    True     2
2   False    3
    True     4

我可以选择一个特定条目 - 例如,

grp == 1 & is_even == True
:

df.loc[(1, True)]
x    2
Name: (1, True), dtype: int64

并且使用

slice
pd.IndexSlice
表示法,我可以为 first 索引级别 (
grp == 1
) 选择特定值,以及第二级别的所有值:

# with slice()
df.loc[slice(1), slice(None)]
             x
grp is_even   
1   False    1
    True     2

# with pd.IndexSlice
idx = pd.IndexSlice
df.loc[idx[1, :]] # note - correct rows selected but grp index level not shown
         x
is_even   
False    1
True     2

但是当我尝试选择第一个索引级别的所有值以及第二个索引级别的特定值(例如

is_even == True
)时,此语法模式失败(第二个索引级别的值上出现 KeyError)。

df.loc[idx[:, True]] # also throws KeyError with df.loc[(slice(None), slice(True))]

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~/anaconda3/envs/betterup-example-analysis/lib/python3.6/site-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
   2645             try:
-> 2646                 return self._engine.get_loc(key)
   2647             except KeyError:
# ...

错误跟踪很长(如果有助于查看全部内容,则可以使用此代码重现),但其中一个片段有一些注释暗示问题所在(以粗体显示):

~/anaconda3/envs/betterup-example-analysis/lib/python3.6/site-packages/pandas/core/indexing.py 在 _getitem_lowerdim(self, tup)
第1371章 第1372章 - > 1373返回self._getitem_nested_tuple(tup) 1374 第1375章

经过一些实验,我发现添加列占位符可以解决该错误。 (这样做还会恢复上面
IndexSlice
示例中缺失的第一个索引级别。) df.loc[idx[:, True], :] x grp is_even 1 True 2 2 True 4

我还发现我可以通过

query

到达那里:

df.query('is_even == True')
所以我很高兴我有一个修复程序,但我的 Pandas-fu 还不够强大,无法理解

为什么

在不包含列占位符的情况下会发生错误。如果有人可以帮助我了解这里发生的事情,我将非常感激!

熊猫版本:1.0.5
Python版本:3.6.15

idx[:, True]

实际上只是一个要创建的包装器:

(slice(None, None, None), True)
python pandas multi-index
1个回答
0
投票
因此,当您将其传递给切片时,这将使用第一部分作为索引,第二部分作为列。

通过执行 
df.loc[idx[:, True], :]

,您明确表示列切片器是
:

进一步的演示是尝试运行

df.loc[idx[:, 'x']]

,这将正确地对列进行切片 
x

© www.soinside.com 2019 - 2024. All rights reserved.