Skip to content

Commit 6146da2

Browse files
lukemanleymeeseeksmachine
authored andcommitted
Backport PR pandas-dev#57101: REGR: Index.join raising TypeError when joining an empty index to a mixed type index
1 parent f577be2 commit 6146da2

File tree

3 files changed

+53
-32
lines changed

3 files changed

+53
-32
lines changed

doc/source/whatsnew/v2.2.1.rst

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Fixed regressions
1919
- Fixed regression in :func:`wide_to_long` raising an ``AttributeError`` for string columns (:issue:`57066`)
2020
- Fixed regression in :meth:`DataFrameGroupBy.idxmin`, :meth:`DataFrameGroupBy.idxmax`, :meth:`SeriesGroupBy.idxmin`, :meth:`SeriesGroupBy.idxmax` ignoring the ``skipna`` argument (:issue:`57040`)
2121
- Fixed regression in :meth:`DataFrameGroupBy.idxmin`, :meth:`DataFrameGroupBy.idxmax`, :meth:`SeriesGroupBy.idxmin`, :meth:`SeriesGroupBy.idxmax` where values containing the minimum or maximum value for the dtype could produce incorrect results (:issue:`57040`)
22+
- Fixed regression in :meth:`Index.join` raising ``TypeError`` when joining an empty index to a non-empty index containing mixed dtype values (:issue:`57048`)
2223
- Fixed regression in :meth:`Series.pct_change` raising a ``ValueError`` for an empty :class:`Series` (:issue:`57056`)
2324

2425
.. ---------------------------------------------------------------------------

pandas/core/indexes/base.py

+33-32
Original file line numberDiff line numberDiff line change
@@ -4615,38 +4615,12 @@ def join(
46154615
if level is not None and (self._is_multi or other._is_multi):
46164616
return self._join_level(other, level, how=how)
46174617

4618-
lidx: np.ndarray | None
4619-
ridx: np.ndarray | None
4620-
4621-
if len(other) == 0:
4622-
if how in ("left", "outer"):
4623-
if sort and not self.is_monotonic_increasing:
4624-
lidx = self.argsort()
4625-
join_index = self.take(lidx)
4626-
else:
4627-
lidx = None
4628-
join_index = self._view()
4629-
ridx = np.broadcast_to(np.intp(-1), len(join_index))
4630-
return join_index, lidx, ridx
4631-
elif how in ("right", "inner", "cross"):
4632-
join_index = other._view()
4633-
lidx = np.array([], dtype=np.intp)
4634-
return join_index, lidx, None
4635-
4636-
if len(self) == 0:
4637-
if how in ("right", "outer"):
4638-
if sort and not other.is_monotonic_increasing:
4639-
ridx = other.argsort()
4640-
join_index = other.take(ridx)
4641-
else:
4642-
ridx = None
4643-
join_index = other._view()
4644-
lidx = np.broadcast_to(np.intp(-1), len(join_index))
4645-
return join_index, lidx, ridx
4646-
elif how in ("left", "inner", "cross"):
4647-
join_index = self._view()
4648-
ridx = np.array([], dtype=np.intp)
4649-
return join_index, None, ridx
4618+
if len(self) == 0 or len(other) == 0:
4619+
try:
4620+
return self._join_empty(other, how, sort)
4621+
except TypeError:
4622+
# object dtype; non-comparable objects
4623+
pass
46504624

46514625
if self.dtype != other.dtype:
46524626
dtype = self._find_common_type_compat(other)
@@ -4681,6 +4655,33 @@ def join(
46814655

46824656
return self._join_via_get_indexer(other, how, sort)
46834657

4658+
@final
4659+
def _join_empty(
4660+
self, other: Index, how: JoinHow, sort: bool
4661+
) -> tuple[Index, npt.NDArray[np.intp] | None, npt.NDArray[np.intp] | None]:
4662+
assert len(self) == 0 or len(other) == 0
4663+
_validate_join_method(how)
4664+
4665+
lidx: np.ndarray | None
4666+
ridx: np.ndarray | None
4667+
4668+
if len(other):
4669+
how = cast(JoinHow, {"left": "right", "right": "left"}.get(how, how))
4670+
join_index, ridx, lidx = other._join_empty(self, how, sort)
4671+
elif how in ["left", "outer"]:
4672+
if sort and not self.is_monotonic_increasing:
4673+
lidx = self.argsort()
4674+
join_index = self.take(lidx)
4675+
else:
4676+
lidx = None
4677+
join_index = self._view()
4678+
ridx = np.broadcast_to(np.intp(-1), len(join_index))
4679+
else:
4680+
join_index = other._view()
4681+
lidx = np.array([], dtype=np.intp)
4682+
ridx = None
4683+
return join_index, lidx, ridx
4684+
46844685
@final
46854686
def _join_via_get_indexer(
46864687
self, other: Index, how: JoinHow, sort: bool

pandas/tests/reshape/merge/test_join.py

+19
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,25 @@ def test_join_empty(left_empty, how, exp):
10421042
tm.assert_frame_equal(result, expected)
10431043

10441044

1045+
def test_join_empty_uncomparable_columns():
1046+
# GH 57048
1047+
df1 = DataFrame()
1048+
df2 = DataFrame(columns=["test"])
1049+
df3 = DataFrame(columns=["foo", ("bar", "baz")])
1050+
1051+
result = df1 + df2
1052+
expected = DataFrame(columns=["test"])
1053+
tm.assert_frame_equal(result, expected)
1054+
1055+
result = df2 + df3
1056+
expected = DataFrame(columns=[("bar", "baz"), "foo", "test"])
1057+
tm.assert_frame_equal(result, expected)
1058+
1059+
result = df1 + df3
1060+
expected = DataFrame(columns=[("bar", "baz"), "foo"])
1061+
tm.assert_frame_equal(result, expected)
1062+
1063+
10451064
@pytest.mark.parametrize(
10461065
"how, values",
10471066
[

0 commit comments

Comments
 (0)