@@ -4087,8 +4087,6 @@ def join(
4087
4087
join_index, (left_indexer, right_indexer)
4088
4088
"""
4089
4089
other = ensure_index (other )
4090
- self_is_mi = isinstance (self , ABCMultiIndex )
4091
- other_is_mi = isinstance (other , ABCMultiIndex )
4092
4090
4093
4091
if isinstance (self , ABCDatetimeIndex ) and isinstance (other , ABCDatetimeIndex ):
4094
4092
if (self .tz is None ) ^ (other .tz is None ):
@@ -4108,7 +4106,7 @@ def join(
4108
4106
4109
4107
# try to figure out the join level
4110
4108
# GH3662
4111
- if level is None and (self_is_mi or other_is_mi ):
4109
+ if level is None and (self . _is_multi or other . _is_multi ):
4112
4110
4113
4111
# have the same levels/names so a simple join
4114
4112
if self .names == other .names :
@@ -4117,7 +4115,7 @@ def join(
4117
4115
return self ._join_multi (other , how = how )
4118
4116
4119
4117
# join on the level
4120
- if level is not None and (self_is_mi or other_is_mi ):
4118
+ if level is not None and (self . _is_multi or other . _is_multi ):
4121
4119
return self ._join_level (other , level , how = how )
4122
4120
4123
4121
if len (other ) == 0 and how in ("left" , "outer" ):
@@ -4166,8 +4164,20 @@ def join(
4166
4164
try :
4167
4165
return self ._join_monotonic (other , how = how )
4168
4166
except TypeError :
4167
+ # object dtype; non-comparable objects
4169
4168
pass
4170
4169
4170
+ return self ._join_via_get_indexer (other , how , sort )
4171
+
4172
+ @final
4173
+ def _join_via_get_indexer (
4174
+ self , other : Index , how : str_t , sort : bool
4175
+ ) -> tuple [Index , npt .NDArray [np .intp ] | None , npt .NDArray [np .intp ] | None ]:
4176
+ # Fallback if we do not have any fastpaths available based on
4177
+ # uniqueness/monotonicity
4178
+
4179
+ # Note: at this point we have checked matching dtypes
4180
+
4171
4181
if how == "left" :
4172
4182
join_index = self
4173
4183
elif how == "right" :
@@ -4277,22 +4287,25 @@ def _join_non_unique(
4277
4287
# We only get here if dtypes match
4278
4288
assert self .dtype == other .dtype
4279
4289
4280
- lvalues = self ._get_join_target ()
4281
- rvalues = other ._get_join_target ()
4282
-
4283
4290
left_idx , right_idx = get_join_indexers (
4284
- [lvalues ], [rvalues ], how = how , sort = True
4291
+ [self . _values ], [other . _values ], how = how , sort = True
4285
4292
)
4293
+ mask = left_idx == - 1
4286
4294
4287
- left_idx = ensure_platform_int (left_idx )
4288
- right_idx = ensure_platform_int (right_idx )
4295
+ # error: Argument 1 to "take" of "ExtensionArray" has incompatible
4296
+ # type "ndarray[Any, dtype[signedinteger[Any]]]"; expected "Sequence[int]"
4297
+ join_array = self ._values .take (left_idx ) # type: ignore[arg-type]
4298
+ # error: Argument 1 to "take" of "ExtensionArray" has incompatible type
4299
+ # "ndarray[Any, dtype[signedinteger[Any]]]"; expected "Sequence[int]"
4300
+ right = other ._values .take (right_idx ) # type: ignore[arg-type]
4289
4301
4290
- join_array = np .asarray (lvalues .take (left_idx ))
4291
- mask = left_idx == - 1
4292
- np .putmask (join_array , mask , rvalues .take (right_idx ))
4302
+ if isinstance (join_array , np .ndarray ):
4303
+ np .putmask (join_array , mask , right )
4304
+ else :
4305
+ # error: "ExtensionArray" has no attribute "putmask"
4306
+ join_array .putmask (mask , right ) # type: ignore[attr-defined]
4293
4307
4294
- join_arraylike = self ._from_join_target (join_array )
4295
- join_index = self ._wrap_joined_index (join_arraylike , other )
4308
+ join_index = self ._wrap_joined_index (join_array , other )
4296
4309
4297
4310
return join_index , left_idx , right_idx
4298
4311
@@ -4445,7 +4458,9 @@ def _get_leaf_sorter(labels: list[np.ndarray]) -> npt.NDArray[np.intp]:
4445
4458
return join_index , left_indexer , right_indexer
4446
4459
4447
4460
@final
4448
- def _join_monotonic (self , other : Index , how : str_t = "left" ):
4461
+ def _join_monotonic (
4462
+ self , other : Index , how : str_t = "left"
4463
+ ) -> tuple [Index , npt .NDArray [np .intp ] | None , npt .NDArray [np .intp ] | None ]:
4449
4464
# We only get here with matching dtypes
4450
4465
assert other .dtype == self .dtype
4451
4466
0 commit comments