The most straightforward way is with .loc
:
>>> data.loc[:, (['one', 'two'], ['a', 'b'])]
one two
a b a b
0 0.4 -0.6 -0.7 0.9
1 0.1 0.4 0.5 -0.3
2 0.7 -1.6 0.7 -0.8
3 -0.9 2.6 1.9 0.6
Remember that []
and ()
have special meaning when dealing with a MultiIndex
object:
(…) a tuple is interpreted as one multi-level key
(…) a list is used to specify several keys [on the same level]
(…) a tuple of lists refer to several values within a level
When we write (['one', 'two'], ['a', 'b'])
, the first list inside the tuple specifies all the values we want from the 1st level of the MultiIndex
. The second list inside the tuple specifies all the values we want from the 2nd level of the MultiIndex
.
Edit 1: Another possibility is to use slice(None)
to specify that we want anything from the first level (works similarly to slicing with :
in lists). And then specify which columns from the second level we want.
>>> data.loc[:, (slice(None), ["a", "b"])]
one two
a b a b
0 0.4 -0.6 -0.7 0.9
1 0.1 0.4 0.5 -0.3
2 0.7 -1.6 0.7 -0.8
3 -0.9 2.6 1.9 0.6
If the syntax slice(None)
does appeal to you, then another possibility is to use pd.IndexSlice
, which helps slicing frames with more elaborate indices.
>>> data.loc[:, pd.IndexSlice[:, ["a", "b"]]]
one two
a b a b
0 0.4 -0.6 -0.7 0.9
1 0.1 0.4 0.5 -0.3
2 0.7 -1.6 0.7 -0.8
3 -0.9 2.6 1.9 0.6
When using pd.IndexSlice
, we can use :
as usual to slice the frame.
Source: MultiIndex / Advanced Indexing, How to use slice(None)