2

Input :

midx = pd.MultiIndex.from_product([['A0','A1'], ['B0','B1','B2','B3']])
columns = ['foo', 'bar']
t = pd.DataFrame(np.arange(16).reshape((len(midx), len(columns))),
                    index=midx, columns=columns)

Output:

In [6]: t
Out[6]:
       foo  bar
A0 B0    0    1
   B1    2    3
   B2    4    5
   B3    6    7
A1 B0    8    9
   B1   10   11
   B2   12   13
   B3   14   15

Question:

Let v = pd.IndexSlice['A0','B0':'B1']. I can access t.loc[v,:]:

In [13]: t.loc[v,:]
Out[13]:
       foo  bar
A0 B0    0    1
   B1    2    3

From [v,v], how can I get the following dataframe?

In [13]: f([v,v])
Out[13]:
       foo  bar
A0 B0    0    1
   B1    2    3
   B0    0    1
   B1    2    3

I can't specify a list of those multi-index slicers: t.loc[[v,v],:] will raise an Exception: Unashable type: 'slice'. Why is it so? When using scalars, I can easily list the desired locs: t.loc[[('A0','B0'),('A0','B1')],:].

Literal
  • 757
  • 6
  • 16
  • Please describe the expected output and we can tell you the best way for that slicing operation. Might also be worth looking into https://stackoverflow.com/questions/53927460/select-rows-in-pandas-multiindex-dataframe – cs95 Jan 14 '21 at 18:13
  • Nope. I think this beyound the current limits of indexing multiIindex dataframes. Here is a workaround `pd.concat([t.loc[v,:]]*2)` – Scott Boston Jan 14 '21 at 19:49
  • 1
    Yep, I ended up using concat. I was just wondering... I thought `t.loc[[v,v],:]` would have been a good syntax to achieve that. Thanks ! – Literal Jan 14 '21 at 19:56

2 Answers2

1

Try:

t.loc[tuple(zip(v, v)),:]

It should be :

u = (['A0', 'A1'], [slice('B0', 'B1', None), slice('B0', 'B1', None)])

try to have it in the above form.

t.loc[u,:]

        foo bar
A0  B0  0   1
    B1  2   3
A1  B0  8   9
    B1  10  11
Pygirl
  • 12,969
  • 5
  • 30
  • 43
1

Use a little known nor used parameter axis=0 of loc:

You can also specify the axis argument to .loc to interpret the passed slicers on a single axis.

Advanced indexing with hierarchical index

t.loc(axis=0)[v]

Output:

       foo  bar
A0 B0    0    1
   B1    2    3

Work around per updated comments and question clarification:

pd.concat([t.loc[v,:]]*2)

Output:

       foo  bar
A0 B0    0    1
   B1    2    3
   B0    0    1
   B1    2    3
Scott Boston
  • 147,308
  • 15
  • 139
  • 187