Skip to content

Commit 381dd06

Browse files
authored
PERF: tighten _should_compare for MultiIndex (pandas-dev#42231)
1 parent b0082d2 commit 381dd06

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

pandas/core/indexes/base.py

+18
Original file line numberDiff line numberDiff line change
@@ -5384,6 +5384,16 @@ def _get_indexer_non_comparable(
53845384
"""
53855385
if method is not None:
53865386
other = unpack_nested_dtype(target)
5387+
if self._is_multi ^ other._is_multi:
5388+
kind = other.dtype.type if self._is_multi else self.dtype.type
5389+
raise TypeError(
5390+
f"'<' not supported between instances of {kind} and 'tuple'"
5391+
)
5392+
elif self._is_multi and other._is_multi:
5393+
assert self.nlevels != other.nlevels
5394+
# Python allows comparison between tuples of different lengths,
5395+
# but for our purposes such a comparison is not meaningful.
5396+
raise TypeError("'<' not supported between tuples of different lengths")
53875397
raise TypeError(f"Cannot compare dtypes {self.dtype} and {other.dtype}")
53885398

53895399
no_matches = -1 * np.ones(target.shape, dtype=np.intp)
@@ -5513,6 +5523,14 @@ def _should_compare(self, other: Index) -> bool:
55135523

55145524
other = unpack_nested_dtype(other)
55155525
dtype = other.dtype
5526+
if other._is_multi:
5527+
if not self._is_multi:
5528+
# other contains only tuples so unless we are object-dtype,
5529+
# there can never be any matches
5530+
return self._is_comparable_dtype(dtype)
5531+
return self.nlevels == other.nlevels
5532+
# TODO: we can get more specific requiring levels are comparable?
5533+
55165534
return self._is_comparable_dtype(dtype) or is_object_dtype(dtype)
55175535

55185536
def _is_comparable_dtype(self, dtype: DtypeObj) -> bool:

pandas/tests/indexes/multi/test_indexing.py

+9
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,15 @@ def test_get_indexer_kwarg_validation(self):
457457
with pytest.raises(ValueError, match=msg):
458458
mi.get_indexer(mi[:-1], tolerance="piano")
459459

460+
def test_get_indexer_mismatched_nlevels(self):
461+
mi = MultiIndex.from_product([range(3), ["A", "B"]])
462+
463+
other = MultiIndex.from_product([range(3), ["A", "B"], range(2)])
464+
465+
msg = "tuples of different lengths"
466+
with pytest.raises(TypeError, match=msg):
467+
mi.get_indexer(other, method="pad")
468+
460469

461470
def test_getitem(idx):
462471
# scalar

0 commit comments

Comments
 (0)