Skip to content

Commit 6db38b8

Browse files
committed
fixes
1 parent 211085d commit 6db38b8

File tree

5 files changed

+53
-13
lines changed

5 files changed

+53
-13
lines changed

pandas/index.pyx

+2-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,8 @@ cdef inline bint _is_utc(object tz):
556556
cdef class MultiIndexEngine(IndexEngine):
557557

558558
def _call_monotonic(self, object mi):
559-
return mi.is_lexsorted(), mi.is_monotonic, mi.is_unique
559+
# defer these back to the mi iteself
560+
return mi.is_monotonic_increasing, mi.is_monotonic_decreasing, mi.is_unique
560561

561562
def get_backfill_indexer(self, other, limit=None):
562563
# we coerce to ndarray-of-tuples

pandas/indexes/multi.py

+22-9
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,18 @@ def _has_complex_internals(self):
666666

667667
@cache_readonly
668668
def is_monotonic(self):
669+
"""
670+
return if the index is monotonic increasing (only equal or
671+
increasing) values.
672+
"""
673+
return self.is_monotonic_increasing
674+
675+
@cache_readonly
676+
def is_monotonic_increasing(self):
677+
"""
678+
return if the index is monotonic increasing (only equal or
679+
increasing) values.
680+
"""
669681

670682
# reversed() because lexsort() wants the most significant key last.
671683
values = [self._get_level_values(i)
@@ -678,6 +690,14 @@ def is_monotonic(self):
678690
# we have mixed types and np.lexsort is not happy
679691
return Index(self.values).is_monotonic
680692

693+
@property
694+
def is_monotonic_decreasing(self):
695+
"""
696+
return if the index is monotonic decreasing (only equal or
697+
decreasing) values.
698+
"""
699+
return False
700+
681701
@cache_readonly
682702
def is_unique(self):
683703
return not self.duplicated().any()
@@ -1922,15 +1942,8 @@ def partial_selection(key, indexer=None):
19221942

19231943
key = tuple(self[indexer].tolist()[0])
19241944

1925-
try:
1926-
return (self._engine.get_loc(
1927-
_values_from_object(key)), None)
1928-
except ValueError:
1929-
# if we hae a very odd MultiIndex,
1930-
# e.g. with embedded tuples, this might fail
1931-
# TODO: should prob not allow construction of a MI
1932-
# like this in the first place
1933-
return Index(self.values).get_loc(key)
1945+
return (self._engine.get_loc(
1946+
_values_from_object(key)), None)
19341947

19351948
else:
19361949
return partial_selection(key)

pandas/src/hashtable_class_helper.pxi.in

+5-1
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,11 @@ cdef class MultiIndexHashTable(HashTable):
881881
khiter_t k
882882
uint64_t value
883883

884-
value = self.mi._hashed_indexing_key(key)
884+
try:
885+
value = self.mi._hashed_indexing_key(key)
886+
except TypeError:
887+
return False
888+
885889
k = kh_get_uint64(self.table, value)
886890
if k != self.table.n_buckets:
887891
loc = self.table.vals[k]

pandas/tests/frame/test_mutate_columns.py

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# -*- coding: utf-8 -*-
22

33
from __future__ import print_function
4-
4+
import pytest
55
from pandas.compat import range, lrange
66
import numpy as np
77

8-
from pandas import DataFrame, Series, Index
8+
from pandas import DataFrame, Series, Index, MultiIndex
99

1010
from pandas.util.testing import (assert_series_equal,
1111
assert_frame_equal,
@@ -165,6 +165,23 @@ def test_delitem(self):
165165
del self.frame['A']
166166
self.assertNotIn('A', self.frame)
167167

168+
def test_delitem_multiindex(self):
169+
midx = MultiIndex.from_product([['A', 'B'], [1, 2]])
170+
df = DataFrame(np.random.randn(4, 4), columns=midx)
171+
assert len(df.columns) == 4
172+
173+
result = df['A']
174+
assert isinstance(result, DataFrame)
175+
del df['A']
176+
177+
assert len(df.columns) == 2
178+
179+
with pytest.raises(KeyError):
180+
del df[('A',)]
181+
182+
with pytest.raises(KeyError):
183+
del df['A']
184+
168185
def test_pop(self):
169186
self.frame.columns.name = 'baz'
170187

pandas/tests/indexes/test_multi.py

+5
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,11 @@ def test_contains(self):
10461046
self.assertNotIn(('bar', 'two'), self.index)
10471047
self.assertNotIn(None, self.index)
10481048

1049+
def test_contains_top_level(self):
1050+
midx = MultiIndex.from_product([['A', 'B'], [1, 2]])
1051+
assert 'A' in midx
1052+
assert 'A' not in midx._engine
1053+
10491054
def test_contains_with_nat(self):
10501055
# MI with a NaT
10511056
mi = MultiIndex(levels=[['C'],

0 commit comments

Comments
 (0)