diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index e91a25a9e23e8..0dd452c53e3a4 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -115,6 +115,7 @@ if TYPE_CHECKING: from pandas import MultiIndex, RangeIndex, Series + from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin __all__ = ["Index"] @@ -2895,9 +2896,8 @@ def _union(self, other, sort): @final def _wrap_setop_result(self, other, result): - if isinstance(self, (ABCDatetimeIndex, ABCTimedeltaIndex)) and isinstance( - result, np.ndarray - ): + if needs_i8_conversion(self.dtype) and isinstance(result, np.ndarray): + self = cast("DatetimeIndexOpsMixin", self) result = type(self._data)._simple_new(result, dtype=self.dtype) elif is_categorical_dtype(self.dtype) and isinstance(result, np.ndarray): result = Categorical(result, dtype=self.dtype) diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index d1d6013f8e2ed..3fbb4364d112e 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -612,6 +612,13 @@ def insert(self, loc: int, item): # -------------------------------------------------------------------- # Join/Set Methods + _inner_indexer = _join_i8_wrapper(libjoin.inner_join_indexer) + _outer_indexer = _join_i8_wrapper(libjoin.outer_join_indexer) + _left_indexer = _join_i8_wrapper(libjoin.left_join_indexer) + _left_indexer_unique = _join_i8_wrapper( + libjoin.left_join_indexer_unique, with_indexers=False + ) + def _get_join_freq(self, other): """ Get the freq to attach to the result of a join operation. @@ -832,13 +839,6 @@ def _union(self, other, sort): # Join Methods _join_precedence = 10 - _inner_indexer = _join_i8_wrapper(libjoin.inner_join_indexer) - _outer_indexer = _join_i8_wrapper(libjoin.outer_join_indexer) - _left_indexer = _join_i8_wrapper(libjoin.left_join_indexer) - _left_indexer_unique = _join_i8_wrapper( - libjoin.left_join_indexer_unique, with_indexers=False - ) - def join( self, other, how: str = "left", level=None, return_indexers=False, sort=False ): diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 2eda9f9ba41ac..879f2ddbcfcd1 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -31,12 +31,11 @@ ) import pandas.core.common as com import pandas.core.indexes.base as ibase -from pandas.core.indexes.base import ensure_index, maybe_extract_name +from pandas.core.indexes.base import maybe_extract_name from pandas.core.indexes.datetimelike import DatetimeIndexOpsMixin from pandas.core.indexes.datetimes import DatetimeIndex, Index from pandas.core.indexes.extension import inherit_names from pandas.core.indexes.numeric import Int64Index -from pandas.core.ops import get_op_result_name _index_doc_kwargs = dict(ibase._index_doc_kwargs) _index_doc_kwargs.update({"target_klass": "PeriodIndex or list of Periods"}) @@ -580,32 +579,6 @@ def _get_string_slice(self, key: str): except KeyError as err: raise KeyError(key) from err - # ------------------------------------------------------------------------ - # Set Operation Methods - - def _setop(self, other, sort, opname: str): - """ - Perform a set operation by dispatching to the Int64Index implementation. - """ - self._validate_sort_keyword(sort) - self._assert_can_do_setop(other) - res_name = get_op_result_name(self, other) - other = ensure_index(other) - - i8self = Int64Index._simple_new(self.asi8) - i8other = Int64Index._simple_new(other.asi8) - i8result = getattr(i8self, opname)(i8other, sort=sort) - - parr = type(self._data)(np.asarray(i8result, dtype=np.int64), dtype=self.dtype) - result = type(self)._simple_new(parr, name=res_name) - return result - - def _intersection(self, other, sort=False): - return self._setop(other, sort, opname="intersection") - - def _union(self, other, sort): - return self._setop(other, sort, opname="_union") - # ------------------------------------------------------------------------ def memory_usage(self, deep: bool = False) -> int: diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 21b5841a87ef9..fbc7f578d760e 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -685,14 +685,6 @@ def symmetric_difference(self, other, result_name=None, sort=None): # -------------------------------------------------------------------- - @doc(Int64Index.join) - def join(self, other, how="left", level=None, return_indexers=False, sort=False): - if how == "outer" and self is not other: - # note: could return RangeIndex in more circumstances - return self._int64index.join(other, how, level, return_indexers, sort) - - return super().join(other, how, level, return_indexers, sort) - def _concat(self, indexes, name): """ Overriding parent method for the case of all RangeIndex instances. diff --git a/pandas/tests/indexes/period/test_join.py b/pandas/tests/indexes/period/test_join.py index 56ca7a572c49c..e895bb81ea061 100644 --- a/pandas/tests/indexes/period/test_join.py +++ b/pandas/tests/indexes/period/test_join.py @@ -8,6 +8,14 @@ class TestJoin: + def test_join_outer_indexer(self): + pi = period_range("1/1/2000", "1/20/2000", freq="D") + + result = pi._outer_indexer(pi._values, pi._values) + tm.assert_numpy_array_equal(result[0], pi.asi8) + tm.assert_numpy_array_equal(result[1], np.arange(len(pi), dtype=np.int64)) + tm.assert_numpy_array_equal(result[2], np.arange(len(pi), dtype=np.int64)) + def test_joins(self, join_type): index = period_range("1/1/2000", "1/20/2000", freq="D")