From 30fb8c7c8a613e5047927676f660452f3daf1abf Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 3 Jun 2021 11:44:08 -0700 Subject: [PATCH 1/2] REF: do remove DTI._convert_arr_indexer --- pandas/core/indexes/base.py | 8 +++++++- pandas/core/indexes/datetimelike.py | 10 ++++++---- pandas/core/indexing.py | 11 +++++++++++ pandas/tests/indexing/test_indexing.py | 3 +++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 47b99f11c32fe..e1b905684e4e2 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3428,7 +3428,7 @@ def get_indexer( ) -> np.ndarray: # returned ndarray is np.intp method = missing.clean_reindex_fill_method(method) - target = ensure_index(target) + target = self._maybe_cast_listlike_indexer(target) self._check_indexing_method(method) @@ -5694,6 +5694,12 @@ def _maybe_cast_indexer(self, key): return com.cast_scalar_indexer(key) return key + def _maybe_cast_listlike_indexer(self, target) -> Index: + """ + Analogue to maybe_cast_indexer for get_indexer instead of get_loc. + """ + return ensure_index(target) + @final def _validate_indexer(self, form: str_t, key, kind: str_t): """ diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 3dc46f04d1d45..8d9b2cdd953e8 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -49,6 +49,7 @@ TimedeltaArray, ) from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin +import pandas.core.common as com import pandas.core.indexes.base as ibase from pandas.core.indexes.base import ( Index, @@ -593,12 +594,13 @@ def _from_join_target(self, result: np.ndarray): # -------------------------------------------------------------------- - @doc(Index._convert_arr_indexer) - def _convert_arr_indexer(self, keyarr): + @doc(Index._maybe_cast_listlike_indexer) + def _maybe_cast_listlike_indexer(self, keyarr): try: - return self._data._validate_listlike(keyarr, allow_object=True) + res = self._data._validate_listlike(keyarr, allow_object=True) except (ValueError, TypeError): - return super()._convert_arr_indexer(keyarr) + res = com.asarray_tuplesafe(keyarr) + return Index(res, dtype=res.dtype) class DatetimeTimedeltaMixin(DatetimeIndexOpsMixin): diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index d5555561088eb..44360431b2ca0 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -30,6 +30,7 @@ is_object_dtype, is_scalar, is_sequence, + needs_i8_conversion, ) from pandas.core.dtypes.concat import concat_compat from pandas.core.dtypes.generic import ( @@ -1297,6 +1298,16 @@ def _get_listlike_indexer(self, key, axis: int): keyarr, indexer, new_indexer = ax._reindex_non_unique(keyarr) self._validate_read_indexer(keyarr, indexer, axis) + + if needs_i8_conversion(ax.dtype): + keyarr = ax.take(indexer) + if isinstance(key, list) or ( + isinstance(key, type(ax)) and key.freq is None + ): + # DTI/TDI.take can infer a freq in some cases when we dont want one + if keyarr.dtype.kind in ["m", "M"]: + keyarr = keyarr._with_freq(None) + return keyarr, indexer def _validate_read_indexer(self, key, indexer, axis: int): diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index 772aa97c47233..7ffd5b6673053 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -94,6 +94,8 @@ def test_getitem_ndarray_3d( msgs.append("Index data must be 1-dimensional") if isinstance(index, pd.IntervalIndex) and indexer_sli is tm.iloc: msgs.append("Index data must be 1-dimensional") + if isinstance(index, (pd.TimedeltaIndex, pd.DatetimeIndex, pd.PeriodIndex)): + msgs.append("Data must be 1-dimensional") if len(index) == 0 or isinstance(index, pd.MultiIndex): msgs.append("positional indexers are out-of-bounds") msg = "|".join(msgs) @@ -127,6 +129,7 @@ def test_setitem_ndarray_3d(self, index, frame_or_series, indexer_sli): r"Buffer has wrong number of dimensions \(expected 1, got 3\)", "Cannot set values with ndim > 1", "Index data must be 1-dimensional", + "Data must be 1-dimensional", "Array conditional must be same shape as self", ] ) From 03ef15fa12019111e1d756d94d461e01ee13b7ac Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 3 Jun 2021 17:29:58 -0700 Subject: [PATCH 2/2] post-merge fixup --- pandas/core/indexing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index c4f298428ab61..4f55459040bc0 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -1308,11 +1308,11 @@ def _get_listlike_indexer(self, key, axis: int): # For CategoricalIndex take instead of reindex to preserve dtype. # For IntervalIndex this is to map integers to the Intervals they match to. keyarr = ax.take(indexer) - if isinstance(key, list) or ( - isinstance(key, type(ax)) and key.freq is None - ): + if keyarr.dtype.kind in ["m", "M"]: # DTI/TDI.take can infer a freq in some cases when we dont want one - if keyarr.dtype.kind in ["m", "M"]: + if isinstance(key, list) or ( + isinstance(key, type(ax)) and key.freq is None + ): keyarr = keyarr._with_freq(None) return keyarr, indexer