Pandas DataFrame-如何检索MultiIndex级别的特定组合

时间:2018-10-14 00:03:01

标签: python pandas dataframe slice multi-index

我有以下使用三级MultiIndex的DataFrame:

In [1]: iterables = [[1, 2], ['foo', 'bar'], ['one', 'two']]
   ...: midx = pd.MultiIndex.from_product(iterables)
   ...: df = pd.DataFrame(np.random.randn(8), index=midx)
   ...: df

Out[1]:
                  0
1 foo one -0.217594
      two -1.361612
  bar one  2.477790
      two  0.874409
2 foo one  0.403577
      two  0.076111
  bar one  1.423512
      two  0.047898

我想对索引进行切片,以便保留所有第一级,同时仅保留第二级和第二级的以下组合:('foo', 'one')('bar', 'two')。也就是说,我希望我的输出看起来像这样:

                  0
1 foo one -0.217594
  bar two  0.874409
2 foo one  0.403577
  bar two  0.047898

例如,是否可以使用.loc之类的属性在一行中完成此操作?


我知道我可以使用.xs函数分别截取所需组合的横截面,但是我更喜欢较短,更像切片的语法。具体来说,对于我的用例而言,单线很重要。

似乎应该可以进行以下操作:

df.loc[[(slice(None), 'foo', 'one'), (slice(None), 'bar', 'two')]]

但这会导致TypeError: unhashable type: 'slice'

3 个答案:

答案 0 :(得分:2)

您可以通过首先删除第一个索引级别,然后将pd.Index.isin与元组列表一起使用来构造布尔掩码:

df_masked = df[df.index.droplevel(0).isin([('foo', 'one'), ('bar', 'two')])]

print(df_masked)

                  0
1 foo one  1.510316
  bar two  0.260862
2 foo one  0.813745
  bar two  0.023386

答案 1 :(得分:2)

这是基于DataFrame.query的解决方案。根据{{​​3}},您的MultiIndex具有未命名的级别,但是可以使用特殊名称k来访问级别ilevel_k:“如果MultiIndex的级别未命名,则可以使用特殊名称来引用它们。”

query_string = ('(ilevel_1 == "foo" & ilevel_2 == "one") | '
                '(ilevel_1 == "bar" & ilevel_2 == "two")')

df.query(query_string)
                  0
1 foo one -0.217594
  bar two  0.874409
2 foo one  0.403577
  bar two  0.047898

答案 2 :(得分:0)

jpp和Peter的解决方案很好。如果有人发现它有用,这是使用系列作为过滤器的另一种方法。

images/test.png