【问题标题】:Pandas DataFrame - How to retrieve specific combinations of MultiIndex levelsPandas DataFrame - 如何检索 MultiIndex 级别的特定组合
【发布时间】:2019-03-18 19:09:36
【问题描述】:

我有以下使用三级 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'

【问题讨论】:

    标签: python pandas dataframe slice multi-index


    【解决方案1】:

    您可以通过首先删除第一个索引级别然后将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
    

    【讨论】:

      【解决方案2】:

      这是基于DataFrame.query 的解决方案。您的 MultiIndex 有未命名的级别,但级别 k 可以使用特殊名称 ilevel_k 访问,根据 the docs:“如果 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
      

      【讨论】:

        【解决方案3】:

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

        f = pd.Series([True]*len(midx), index=midx)
        f.loc[:,'foo','two'] = False
        f.loc[:,'bar','one'] = False
        
        print(df[f[df.index]])
                          0
        1 foo one -0.185593
          bar two -1.265191
        2 foo one  0.490959
          bar two  0.414753
        

        【讨论】:

          猜你喜欢
          • 2019-11-19
          • 2015-07-19
          • 2015-05-22
          • 1970-01-01
          • 2019-03-05
          • 2019-01-26
          • 1970-01-01
          • 2023-03-10
          相关资源
          最近更新 更多