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?