diff --git a/pandas/_libs/index.pyx b/pandas/_libs/index.pyx index c511fa85d2ec4..31b507e9b7800 100644 --- a/pandas/_libs/index.pyx +++ b/pandas/_libs/index.pyx @@ -84,7 +84,7 @@ cdef class IndexEngine: if self.over_size_threshold and self.is_monotonic_increasing: if not self.is_unique: return self._get_loc_duplicates(val) - values = self._get_index_values() + values = self.values self._check_type(val) try: @@ -116,7 +116,7 @@ cdef class IndexEngine: Py_ssize_t diff if self.is_monotonic_increasing: - values = self._get_index_values() + values = self.values try: left = values.searchsorted(val, side='left') right = values.searchsorted(val, side='right') @@ -139,7 +139,7 @@ cdef class IndexEngine: cdef: ndarray[uint8_t, ndim=1, cast=True] indexer - indexer = self._get_index_values() == val + indexer = self.values == val return self._unpack_bool_indexer(indexer, val) cdef _unpack_bool_indexer(self, @@ -199,7 +199,7 @@ cdef class IndexEngine: cdef: bint is_unique try: - values = self._get_index_values() + values = self.values self.monotonic_inc, self.monotonic_dec, is_unique = \ self._call_monotonic(values) except TypeError: @@ -214,17 +214,14 @@ cdef class IndexEngine: self.unique = 1 self.need_unique_check = 0 - cdef ndarray _get_index_values(self): - return self.values - cdef _call_monotonic(self, values): return algos.is_monotonic(values, timelike=False) def get_backfill_indexer(self, other: np.ndarray, limit=None) -> np.ndarray: - return algos.backfill(self._get_index_values(), other, limit=limit) + return algos.backfill(self.values, other, limit=limit) def get_pad_indexer(self, other: np.ndarray, limit=None) -> np.ndarray: - return algos.pad(self._get_index_values(), other, limit=limit) + return algos.pad(self.values, other, limit=limit) cdef _make_hash_table(self, Py_ssize_t n): raise NotImplementedError @@ -243,7 +240,7 @@ cdef class IndexEngine: if not self.is_mapping_populated: - values = self._get_index_values() + values = self.values self.mapping = self._make_hash_table(len(values)) self._call_map_locations(values) @@ -291,7 +288,7 @@ cdef class IndexEngine: bint d_has_nan = False, stargets_has_nan = False, need_nan_check = True self._ensure_mapping_populated() - values = np.array(self._get_index_values(), copy=False) + values = self.values stargets = set(targets) n = len(values) @@ -411,9 +408,6 @@ cdef class ObjectEngine(IndexEngine): cdef class DatetimeEngine(Int64Engine): - cdef str _get_box_dtype(self): - return 'M8[ns]' - cdef int64_t _unbox_scalar(self, scalar) except? -1: # NB: caller is responsible for ensuring tzawareness compat # before we get here @@ -431,16 +425,13 @@ cdef class DatetimeEngine(Int64Engine): if self.over_size_threshold and self.is_monotonic_increasing: if not self.is_unique: return self._get_loc_duplicates(conv) - values = self._get_index_values() + values = self.values loc = values.searchsorted(conv, side='left') return values[loc] == conv self._ensure_mapping_populated() return conv in self.mapping - cdef ndarray _get_index_values(self): - return self.values.view('i8') - cdef _call_monotonic(self, values): return algos.is_monotonic(values, timelike=True) @@ -462,7 +453,7 @@ cdef class DatetimeEngine(Int64Engine): if self.over_size_threshold and self.is_monotonic_increasing: if not self.is_unique: return self._get_loc_duplicates(conv) - values = self._get_index_values() + values = self.values loc = values.searchsorted(conv, side='left') @@ -479,35 +470,9 @@ cdef class DatetimeEngine(Int64Engine): except KeyError: raise KeyError(val) - def get_indexer_non_unique(self, ndarray targets): - # we may get datetime64[ns] or timedelta64[ns], cast these to int64 - return super().get_indexer_non_unique(targets.view("i8")) - - def get_indexer(self, ndarray values) -> np.ndarray: - self._ensure_mapping_populated() - if values.dtype != self._get_box_dtype(): - return np.repeat(-1, len(values)).astype(np.intp) - values = np.asarray(values).view('i8') - return self.mapping.lookup(values) - - def get_pad_indexer(self, other: np.ndarray, limit=None) -> np.ndarray: - if other.dtype != self._get_box_dtype(): - return np.repeat(-1, len(other)).astype(np.intp) - other = np.asarray(other).view('i8') - return algos.pad(self._get_index_values(), other, limit=limit) - - def get_backfill_indexer(self, other: np.ndarray, limit=None) -> np.ndarray: - if other.dtype != self._get_box_dtype(): - return np.repeat(-1, len(other)).astype(np.intp) - other = np.asarray(other).view('i8') - return algos.backfill(self._get_index_values(), other, limit=limit) - cdef class TimedeltaEngine(DatetimeEngine): - cdef str _get_box_dtype(self): - return 'm8[ns]' - cdef int64_t _unbox_scalar(self, scalar) except? -1: if not (isinstance(scalar, _Timedelta) or scalar is NaT): raise TypeError(scalar) diff --git a/pandas/_libs/index_class_helper.pxi.in b/pandas/_libs/index_class_helper.pxi.in index d6c5bfc9d1839..f1dbc3780011f 100644 --- a/pandas/_libs/index_class_helper.pxi.in +++ b/pandas/_libs/index_class_helper.pxi.in @@ -55,7 +55,7 @@ cdef class {{name}}Engine(IndexEngine): self._check_type(val) - values = self._get_index_values() + values = self.values try: with warnings.catch_warnings(): # e.g. if values is float64 and `val` is a str, suppress warning diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 104dcbf62940c..95387c9557b1a 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -890,7 +890,12 @@ def ravel(self, order="C"): FutureWarning, stacklevel=2, ) - values = self._get_engine_target() + if needs_i8_conversion(self.dtype): + # Item "ndarray[Any, Any]" of "Union[ExtensionArray, ndarray[Any, Any]]" + # has no attribute "_ndarray" + values = self._data._ndarray # type: ignore[union-attr] + else: + values = self._get_engine_target() return values.ravel(order=order) def view(self, cls=None): diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 3211d1f2b720d..d29cb519df1b0 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -503,7 +503,8 @@ def _wrap_joined_index(self, joined, other): result._data._freq = self._get_join_freq(other) return result - def _get_join_target(self) -> np.ndarray: + def _get_engine_target(self) -> np.ndarray: + # engine methods and libjoin methods need dt64/td64 values cast to i8 return self._data._ndarray.view("i8") def _from_join_target(self, result: np.ndarray):