Skip to content

Commit

Permalink
BUG: fix MultiIndex bugs described in #1401
Browse files Browse the repository at this point in the history
  • Loading branch information
wesm committed Jun 11, 2012
1 parent dfaf0ea commit 3b32dab
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 4 deletions.
1 change: 1 addition & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ pandas 0.8.0
- Enable assignment of rows in mixed-type DataFrame via .ix (#1432)
- Reset index mapping when grouping Series in Cython (#1423)
- Fix outer/inner DataFrame.join with non-unique indexes (#1421)
- Fix MultiIndex groupby bugs with empty lower levels (#1401)

pandas 0.7.3
============
Expand Down
12 changes: 9 additions & 3 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,15 @@ def __delitem__(self, key):
Delete item
"""
deleted = False
if (hasattr(self,'columns') and
isinstance(self.columns, MultiIndex)
and key not in self.columns):

maybe_shortcut = False
if hasattr(self,'columns') and isinstance(self.columns, MultiIndex):
try:
maybe_shortcut = key not in self.columns._engine
except TypeError:
pass

if maybe_shortcut:
# Allow shorthand to delete all columns whose first len(key)
# elements match key:
if not isinstance(key,tuple):
Expand Down
8 changes: 7 additions & 1 deletion pandas/core/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,13 @@ def _get_grouper(obj, key=None, axis=0, level=None, sort=True):
exclusions = []
for i, (gpr, level) in enumerate(zip(keys, levels)):
name = None
if _is_label_like(gpr):
try:
obj._data.items.get_loc(gpr)
in_axis = True
except Exception:
in_axis = False

if _is_label_like(gpr) or in_axis:
exclusions.append(gpr)
name = gpr
gpr = obj[gpr]
Expand Down
9 changes: 9 additions & 0 deletions pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,15 @@ def nlevels(self):
def levshape(self):
return tuple(len(x) for x in self.levels)

def __contains__(self, key):
hash(key)
# work around some kind of odd cython bug
try:
self.get_loc(key)
return True
except KeyError:
return False

def __reduce__(self):
"""Necessary for making this object picklable"""
object_state = list(np.ndarray.__reduce__(self))
Expand Down
25 changes: 25 additions & 0 deletions pandas/tests/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -1963,6 +1963,31 @@ def afunc(data):

assert_frame_equal(closure_bad, closure_good)

def test_multiindex_columns_empty_level(self):
l = [['count', 'values'], ['to filter', '']]
midx = MultiIndex.from_tuples(l)

df = DataFrame([[1L, 'A']], columns=midx)

grouped = df.groupby('to filter').groups
self.assert_(np.array_equal(grouped['A'], [0]))

grouped = df.groupby([('to filter', '')]).groups
self.assert_(np.array_equal(grouped['A'], [0]))

df = DataFrame([[1L, 'A'], [2L, 'B']], columns=midx)

expected = df.groupby('to filter').groups
result = df.groupby([('to filter', '')]).groups
self.assertEquals(result, expected)

df = DataFrame([[1L, 'A'], [2L, 'A']], columns=midx)

expected = df.groupby('to filter').groups
result = df.groupby([('to filter', '')]).groups
self.assertEquals(result, expected)


def _check_groupby(df, result, keys, field, f=lambda x: x.sum()):
tups = map(tuple, df[keys].values)
tups = com._asarray_tuplesafe(tups)
Expand Down

0 comments on commit 3b32dab

Please sign in to comment.