我有3个级别的MultiIndex的熊猫数据框。我试图根据与两个级别相对应的值列表来提取此数据框的行。
我有这样的事情:
ix = pd.MultiIndex.from_product([[1, 2, 3], ['foo', 'bar'], ['baz', 'can']], names=['a', 'b', 'c']) data = np.arange(len(ix)) df = pd.DataFrame(data, index=ix, columns=['hi']) print(df) hi a b c 1 foo baz 0 can 1 bar baz 2 can 3 2 foo baz 4 can 5 bar baz 6 can 7 3 foo baz 8 can 9 bar baz 10 can 11
现在,我要获取索引级别为“ b”和“ c”的所有行:
ix_use = pd.MultiIndex.from_tuples([('foo', 'can'), ('bar', 'baz')], names=['b', 'c'])
即值的hi具有('foo', 'can')或('bar', 'baz')在水平b和c分别为:(1, 2, 5, 6, 9, 10)。
hi
('foo', 'can')
('bar', 'baz')
b
c
(1, 2, 5, 6, 9, 10)
所以我想slice(None)在第一级上学习一个,并在第二级和第三级上提取特定的元组。
slice(None)
最初,我认为将多索引对象传递给.loc会拉出我想要的值/级别,但这是行不通的。做这样的事情的最好方法是什么?
这是获取切片的一种方法:
df.sort_index(inplace=True) idx = pd.IndexSlice df.loc[idx[:, ('foo','bar'), 'can'], :]
屈服
hi a b c 1 bar can 3 foo can 1 2 bar can 7 foo can 5 3 bar can 11 foo can 9
请注意,您可能需要先对MultiIndex排序,然后才能对其进行切片。好了,熊猫足以警告您是否需要这样做:
KeyError: 'MultiIndex Slicing requires the index to be fully lexsorted tuple len (3), lexsort depth (1)'
您可以在文档中阅读更多有关如何使用切片器的信息
如果由于某种原因无法使用切片器,则可以使用以下.isin()方法获取相同的切片:
.isin()
df[df.index.get_level_values('b').isin(ix_use.get_level_values(0)) & df.index.get_level_values('c').isin(ix_use.get_level_values(1))]
这显然不是那么简洁。
更新:
对于您在此处更新的条件,可以采用以下方法:
cond1 = (df.index.get_level_values('b').isin(['foo'])) & (df.index.get_level_values('c').isin(['can'])) cond2 = (df.index.get_level_values('b').isin(['bar'])) & (df.index.get_level_values('c').isin(['baz'])) df[cond1 | cond2]
生产:
hi a b c 1 foo can 1 bar baz 2 2 foo can 5 bar baz 6 3 foo can 9 bar baz 10