小编典典

如何将一个MultiIndex DataFrame与另一个的MultiIndex切片

python

我有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')在水平bc分别为:(1, 2, 5, 6, 9, 10)

所以我想slice(None)在第一级上学习一个,并在第二级和第三级上提取特定的元组。

最初,我认为将多索引对象传递给.loc会拉出我想要的值/级别,但这是行不通的。做这样的事情的最好方法是什么?


阅读 208

收藏
2020-12-20

共1个答案

小编典典

这是获取切片的一种方法:

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()方法获取相同的切片:

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
2020-12-20