pandas: slice a MultiIndex by range of secondary index

As Robbie-Clarken answers, since 0.14 you can pass a slice in the tuple you pass to loc:

In [11]: s.loc[('b', slice(2, 10))]
Out[11]:
b  2   -0.65394
   4    0.08227
dtype: float64

Indeed, you can pass a slice for each level:

In [12]: s.loc[(slice('a', 'b'), slice(2, 10))]
Out[12]:
a  5    0.27919
b  2   -0.65394
   4    0.08227
dtype: float64

Note: the slice is inclusive.


Old answer:

You can also do this using:

s.ix[1:10, "b"]

(It's good practice to do in a single ix/loc/iloc since this version allows assignment.)

This answer was written prior to the introduction of iloc in early 2013, i.e. position/integer location - which may be preferred in this case. The reason it was created was to remove the ambiguity from integer-indexed pandas objects, and be more descriptive: "I'm slicing on position".

s["b"].iloc[1:10]

That said, I kinda disagree with the docs that ix is:

most robust and consistent way

it's not, the most consistent way is to describe what you're doing:

  • use loc for labels
  • use iloc for position
  • use ix for both (if you really have to)

Remember the zen of python:

explicit is better than implicit


As of pandas 0.14.0 it is possible to slice multi-indexed objects by providing .loc a tuple containing slice objects:

In [2]: s.loc[('b', slice(2, 10))]
Out[2]:
b  2   -1.206052
   4   -0.735682
dtype: float64

Since pandas 0.15.0 this works:

s.loc['b', 2:10]

Output:

b  2   -0.503023
   4    0.704880
dtype: float64

With a DataFrame it's slightly different (source):

df.loc(axis=0)['b', 2:10]