请考虑具有多索引的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

我可以 Select 一个特定的条目-比方说,grp == 1 & is_even == True:

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

使用slicepd.IndexSlice表示法,我可以为first索引级别(grp == 1) Select 一个特定值,以及第二个级别的所有值:

# 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

但是,当我try Select 第一个索引级别的all values和第二个索引级别的特定值(例如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 in _getitem_lowerdim(self, tup)
1371 # we may have a nested tuples indexer here
1372 if self._is_nested_tuple_indexer(tup):
-> 1373 return self._getitem_nested_tuple(tup)
1374
1375 # we maybe be using a tuple to represent multiple dimensions here

经过一些试验后,我发现添加一个列占位符可以解决这个错误.(这样做还可以恢复上面IndexSlice个示例中缺失的第一个索引级别.)

df.loc[idx[:, True], :]
             x
grp is_even   
1   True     2
2   True     4

我还发现我可以用query分到达那里:

df.query('is_even == True')

所以我很高兴我有了一个解决方案,但是我的Pandas-Fu还不够强大,不能理解why如果不包括列占位符,错误就会发生.如果有人能帮我弄清楚这里发生了什么,我将不胜感激!

Pandas version: 1.0.5
Python version: 3.6.15

推荐答案

idx[:, True]实际上只是一个包装器来创建:

(slice(None, None, None), True)

因此,当您将其传递给Slice时,它将第一部分用于索引,第二部分用于列.

通过设置为df.loc[idx[:, True], :],您可以明确表示列切片器为:

另一个演示是try 运行df.loc[idx[:, 'x']],这将正确地切片列x.


当运行df.loc[slice(1, True), 'x']时,您不是将1用于第一级,True用于第二级,而是执行以下操作:

df.loc[1:True, 'x']

如果要获取索引(1,True)和列x处的项,请使用:

df.loc[(1, True), 'x']

# 2

如果需要第一级的所有值,则只需要第二级和列x中的True个值:

df.loc[(slice(None), True), 'x']

grp  is_even
1    True       2
2    True       4
Name: x, dtype: int64

Python相关问答推荐

如何最好地处理严重级联的json

无法获得指数曲线_fit来处理日期

我可以使用极点优化这个面向cpu的pandas代码吗?

如何计算部分聚合数据的统计数据

如何在Power Query中按名称和时间总和进行分组

单击Python中的复选框后抓取数据

customtkinter中使用的这个小部件的名称是什么

Python中的Pool.starmap异常处理

比较两个数据帧并并排附加结果(获取性能警告)

Deliveryter Notebook -无法在for循环中更新matplotlib情节(保留之前的情节),也无法使用动画子功能对情节进行动画

根据另一列中的nan重置值后重新加权Pandas列

pandas滚动和窗口中有效观察的最大数量

发生异常:TclMessage命令名称无效.!listbox"

在Python中管理打开对话框

如何使用根据其他值相似的列从列表中获取的中间值填充空NaN数据

如何在Django基于类的视图中有效地使用UTE和RST HTIP方法?

两个pandas的平均值按元素的结果串接元素.为什么?

Pandas—在数据透视表中占总数的百分比

将JSON对象转换为Dataframe

从Windows Python脚本在WSL上运行Linux应用程序