Artturi Björk
Artturi Björk

Reputation: 3893

Slicing a Pandas dataframe with a multiindex by combinations of level values

I 'm looking to slice a Pandas dataframe with a multi index by a list of values for some of the index levels.

import pandas as pd
index = pd.MultiIndex.from_product((('A','B'),
                                    range(2),
                                    ('c','d')))
df = pd.DataFrame(index=index,columns=range(2))

slice_list = [('A',0),('B',1)]

This doesn't work:

df.loc[slice_list,:]

I can get my expected result by doing boolean masking(?):

idx = (((df.index.get_level_values(0) == 'A')
   & (df.index.get_level_values(1) == 0)) |
   ((df.index.get_level_values(0) == 'B')
    & (df.index.get_level_values(1) == 1)))
df.loc[idx]



         0    1
A 0 c  NaN  NaN
    d  NaN  NaN
B 1 c  NaN  NaN
    d  NaN  NaN

But I would much prefer a slicing option.

Upvotes: 0

Views: 141

Answers (2)

Lucas Ford
Lucas Ford

Reputation: 181

You can use pandas.IndexSlice (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.IndexSlice.html).

idx = pd.IndexSlice
slice = idx[['A','B'],[0,1],:]
df.loc[slice,:]

Or something along those lines, I am currently replying from a cell phone so I'm not 100% sure.

Upvotes: 0

jezrael
jezrael

Reputation: 862761

You can use Index.isin with remove last level for 2 levels MultiIndex:

df1 = df[df.index.droplevel(-1).isin(slice_list)]
print (df1)
         0    1
A 0 c  NaN  NaN
    d  NaN  NaN
B 1 c  NaN  NaN
    d  NaN  NaN

Details:

print (df.index.droplevel(-1))
MultiIndex([('A', 0),
            ('A', 0),
            ('A', 1),
            ('A', 1),
            ('B', 0),
            ('B', 0),
            ('B', 1),
            ('B', 1)],
           )

Upvotes: 1

Related Questions