熊猫切片多索引使用字典

时间:2021-03-31 23:41:02

标签: python pandas multi-index

有没有更好的方法从多索引中选择多个值 而不是

df.loc[(slice(None), ['one','seven'], slice(None), ['a','d','l'])]

类似:

df.loc[ {level_1: ['one','two'], level_3: ['a','d','l'] } ]

我试过 df.xs 但这只允许每一级有一个键。

1 个答案:

答案 0 :(得分:0)

示例数据

import pandas as pd

index = pd.MultiIndex.from_product([['A', 'B'], ['a', 'b'], [1, 2, 3]], 
                                   names=['foo', 'bar', 'baz'])
df = pd.DataFrame({'data': range(12)}, index=index)

pd.IndexSlice

它与您的原始选择没有任何不同,但语法稍微紧凑一些,因为您可以使用 : 而不是 slice(None)

idx = pd.IndexSlice
df.loc[idx['A', :, [1,3]]]

#             data
#foo bar baz      
#A   a   1       0
#        3       2
#    b   1       3
#        3       5

带有 np.logical_and.reduce 的自定义函数

该函数本身相当冗长,但在编写完成后,您几乎可以忽略它并处理自文档签名。

您提供一个字典,其中键是级别名称(或对应于该级别编号的整数),值是您要为该级别包含的标签。我添加了一个检查,您可以为多个标签指定一个可迭代对象,例如列表/数组/元组,并为您只需要一个标签的级别指定一个值。

import numpy as np

def get_slice(df, slice_dict):
    m = np.logical_and.reduce(
            [df.index.get_level_values(level).isin(v) if (hasattr(v, '__iter__') and not isinstance(v, str)) 
             else df.index.get_level_values(level) == v 
             for level,v in slice_dict.items()])
    
    return df.loc[m]


get_slice(df, {'foo': 'A', 'baz': [1, 3]})

#             data
#foo bar baz      
#A   a   1       0
#        3       2
#    b   1       3
#        3       5