Skip to content
This repository was archived by the owner on Jul 10, 2024. It is now read-only.

Commit 7939a68

Browse files
BUG: join MultiIndex with overlapping IntervalIndex level (pandas-dev#44096)
`BaseMultiIndexCodesEngine._extract_level_codes` relies on the assumption that `get_indexer()` is always usable as any index level `is_unique`. However, that is not the case for overlapping `IntervalIndex` levels. `get_indexer()` can not be used on an `IntervalIndex` that `is_overlapping` even if it `is_unique`. This patch uses `get_indexer_for()` instead.
1 parent 835c78e commit 7939a68

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,7 @@ Reshaping
702702
- Bug in :meth:`DataFrame.append` failing to retain ``index.name`` when appending a list of :class:`Series` objects (:issue:`44109`)
703703
- Fixed metadata propagation in :meth:`Dataframe.apply` method, consequently fixing the same issue for :meth:`Dataframe.transform`, :meth:`Dataframe.nunique` and :meth:`Dataframe.mode` (:issue:`28283`)
704704
- Bug in :meth:`DataFrame.stack` with ``ExtensionDtype`` columns incorrectly raising (:issue:`43561`)
705+
- Bug in :class:`MultiIndex` failing join operations with overlapping ``IntervalIndex`` levels (:issue:`44096`)
705706
-
706707

707708
Sparse

pandas/_libs/index.pyx

+1-1
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ cdef class BaseMultiIndexCodesEngine:
649649
Integers representing one combination each
650650
"""
651651
zt = [target._get_level_values(i) for i in range(target.nlevels)]
652-
level_codes = [lev.get_indexer(codes) + 1 for lev, codes
652+
level_codes = [lev.get_indexer_for(codes) + 1 for lev, codes
653653
in zip(self.levels, zt)]
654654
return self._codes_to_ints(np.array(level_codes, dtype='uint64').T)
655655

pandas/tests/indexes/multi/test_join.py

+43
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from pandas import (
55
Index,
6+
Interval,
67
MultiIndex,
78
)
89
import pandas._testing as tm
@@ -115,3 +116,45 @@ def test_join_multi_return_indexers():
115116

116117
result = midx1.join(midx2, return_indexers=False)
117118
tm.assert_index_equal(result, midx1)
119+
120+
121+
def test_join_overlapping_interval_level():
122+
# GH 44096
123+
idx_1 = MultiIndex.from_tuples(
124+
[
125+
(1, Interval(0.0, 1.0)),
126+
(1, Interval(1.0, 2.0)),
127+
(1, Interval(2.0, 5.0)),
128+
(2, Interval(0.0, 1.0)),
129+
(2, Interval(1.0, 3.0)), # interval limit is here at 3.0, not at 2.0
130+
(2, Interval(3.0, 5.0)),
131+
],
132+
names=["num", "interval"],
133+
)
134+
135+
idx_2 = MultiIndex.from_tuples(
136+
[
137+
(1, Interval(2.0, 5.0)),
138+
(1, Interval(0.0, 1.0)),
139+
(1, Interval(1.0, 2.0)),
140+
(2, Interval(3.0, 5.0)),
141+
(2, Interval(0.0, 1.0)),
142+
(2, Interval(1.0, 3.0)),
143+
],
144+
names=["num", "interval"],
145+
)
146+
147+
expected = MultiIndex.from_tuples(
148+
[
149+
(1, Interval(0.0, 1.0)),
150+
(1, Interval(1.0, 2.0)),
151+
(1, Interval(2.0, 5.0)),
152+
(2, Interval(0.0, 1.0)),
153+
(2, Interval(1.0, 3.0)),
154+
(2, Interval(3.0, 5.0)),
155+
],
156+
names=["num", "interval"],
157+
)
158+
result = idx_1.join(idx_2, how="outer")
159+
160+
tm.assert_index_equal(result, expected)

0 commit comments

Comments
 (0)