Slice pandas DataFrame by MultiIndex level or sublevel

pandas, python

Solution

I actually upvoted joris's answer... but unfortunately the refactoring he mentions has not happened in 0.14 and is not happening in 0.17 neither. So for the moment let me suggest a quick and dirty solution (obviously derived from Jeff's one):

def filter_by(df, constraints):
    """Filter MultiIndex by sublevels."""
    indexer = [constraints[name] if name in constraints else slice(None)
               for name in df.index.names]
    return df.loc[tuple(indexer)] if len(df.shape) == 1 else df.loc[tuple(indexer),]

pd.Series.filter_by = filter_by
pd.DataFrame.filter_by = filter_by

... to be used as

df.filter_by({'level_name' : value})

where `value` can be indeed a single value, but also a list, a slice...

(untested with Panels and higher dimension elements, but I do expect it to work)

Problem

Inspired by this answer and the lack of an easy answer to this question I found myself writing a little syntactic sugar to make life easier to filter by MultiIndex level. ``` def _filter_series(x, level_name, filter_by): """ Filter a pd.Series or pd.DataFrame x by `filter_by` on the MultiIndex level `level_name` Uses `pd.Index.get_level_values()` in the background. `filter_by` is either a string or an iterable. """ if isinstance(x, pd.Series) or isinstance(x, pd.DataFrame): if type(filter_by) is str: filter_by = [filter_by] index = x.index.get_level_values(level_name).isin(filter_by) return x[index] else: print "Not a pandas object" ``` But if I know the pandas development team (and I'm starting to, slowly!) there's already a nice way to do this, and I just don't know what it is yet! Am I right?

Original source

Related problems