From 31dd9fda152f9da33f5949fcd5e5a571c25ece99 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 15 Nov 2020 14:08:16 -0800 Subject: [PATCH 1/5] DEPR: Index.asi8 --- pandas/core/indexes/base.py | 16 +++++++++++----- pandas/core/tools/numeric.py | 6 ++++-- pandas/core/window/rolling.py | 11 +++++++++-- pandas/tests/indexes/test_common.py | 22 +++++++++++++++++++++- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index cb5641a74e60b..24adca62b839a 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -415,6 +415,11 @@ def asi8(self): ndarray An ndarray with int64 dtype. """ + warnings.warn( + "Index.asi8 is deprecated and will be removed in a future version", + FutureWarning, + stacklevel=2, + ) return None @classmethod @@ -4717,12 +4722,13 @@ def argsort(self, *args, **kwargs) -> np.ndarray: >>> idx[order] Index(['a', 'b', 'c', 'd'], dtype='object') """ - result = self.asi8 - - if result is None: - result = np.array(self) + if needs_i8_conversion(self.dtype): + # TODO: these do not match the underlying EA argsort methods + return self.asi8.argsort(*args, **kwargs) - return result.argsort(*args, **kwargs) + # This works for either ndarray or EA, is overriden + # by RangeIndex, MultIIndex + return self._data.argsort(*args, **kwargs) @final def get_value(self, series: "Series", key): diff --git a/pandas/core/tools/numeric.py b/pandas/core/tools/numeric.py index 32ca83787c4c1..4af32b219d380 100644 --- a/pandas/core/tools/numeric.py +++ b/pandas/core/tools/numeric.py @@ -10,6 +10,7 @@ is_number, is_numeric_dtype, is_scalar, + needs_i8_conversion, ) from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries @@ -123,8 +124,9 @@ def to_numeric(arg, errors="raise", downcast=None): values = arg.values elif isinstance(arg, ABCIndexClass): is_index = True - values = arg.asi8 - if values is None: + if needs_i8_conversion(arg.dtype): + values = arg.asi8 + else: values = arg.values elif isinstance(arg, (list, tuple)): values = np.array(arg, dtype="O") diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index f65452cb2f17f..178a040ea2531 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -337,6 +337,13 @@ def _get_roll_func(self, func_name: str) -> Callable[..., Any]: ) return window_func + @property + def _index_array(self): + # TODO: why do we get here with e.g. MultiIndex? + if needs_i8_conversion(self._on.dtype): + return self._on.asi8 + return None + def _get_window_indexer(self) -> BaseIndexer: """ Return an indexer class that will compute the window start and end bounds @@ -345,7 +352,7 @@ def _get_window_indexer(self) -> BaseIndexer: return self.window if self.is_freq_type: return VariableWindowIndexer( - index_array=self._on.asi8, window_size=self.window + index_array=self._index_array, window_size=self.window ) return FixedWindowIndexer(window_size=self.window) @@ -2143,7 +2150,7 @@ def _get_window_indexer(self) -> GroupbyIndexer: """ rolling_indexer: Type[BaseIndexer] indexer_kwargs: Optional[Dict[str, Any]] = None - index_array = self._on.asi8 + index_array = self._index_array window = self.window if isinstance(self.window, BaseIndexer): rolling_indexer = type(self.window) diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index d15b560419f6d..22fdc31f10ae4 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -13,7 +13,16 @@ from pandas.core.dtypes.common import is_period_dtype, needs_i8_conversion import pandas as pd -from pandas import CategoricalIndex, MultiIndex, RangeIndex +from pandas import ( + CategoricalIndex, + DatetimeIndex, + Int64Index, + MultiIndex, + PeriodIndex, + RangeIndex, + TimedeltaIndex, + UInt64Index, +) import pandas._testing as tm @@ -348,6 +357,17 @@ def test_ravel_deprecation(self, index): with tm.assert_produces_warning(FutureWarning): index.ravel() + def test_asi8_deprecation(self, index): + if isinstance( + index, (Int64Index, UInt64Index, DatetimeIndex, TimedeltaIndex, PeriodIndex) + ): + warn = None + else: + warn = FutureWarning + + with tm.assert_produces_warning(warn): + index.asi8 + @pytest.mark.parametrize("na_position", [None, "middle"]) def test_sort_values_invalid_na_position(index_with_missing, na_position): From f5bada89098168cc935dc8b39c88c5a71bf1f7e2 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 15 Nov 2020 14:08:54 -0800 Subject: [PATCH 2/5] whatsnew --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index e690334a36c5b..520b2eac447e2 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -457,7 +457,7 @@ Deprecations - :class:`Index` methods ``&``, ``|``, and ``^`` behaving as the set operations :meth:`Index.intersection`, :meth:`Index.union`, and :meth:`Index.symmetric_difference`, respectively, are deprecated and in the future will behave as pointwise boolean operations matching :class:`Series` behavior. Use the named set methods instead (:issue:`36758`) - :meth:`Categorical.is_dtype_equal` and :meth:`CategoricalIndex.is_dtype_equal` are deprecated, will be removed in a future version (:issue:`37545`) - :meth:`Series.slice_shift` and :meth:`DataFrame.slice_shift` are deprecated, use :meth:`Series.shift` or :meth:`DataFrame.shift` instead (:issue:`37601`) - +- Deprecated :meth:`Index.asi8` (:issue:`??`) .. --------------------------------------------------------------------------- From 8c667da954b86f23ba8161d510b21413bd469548 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 15 Nov 2020 14:11:47 -0800 Subject: [PATCH 3/5] GH refs --- doc/source/whatsnew/v1.2.0.rst | 2 +- pandas/core/indexes/base.py | 2 +- pandas/tests/indexes/test_common.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index c84ad4c91558c..efc9f776aba3d 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -458,7 +458,7 @@ Deprecations - :meth:`Categorical.is_dtype_equal` and :meth:`CategoricalIndex.is_dtype_equal` are deprecated, will be removed in a future version (:issue:`37545`) - :meth:`Series.slice_shift` and :meth:`DataFrame.slice_shift` are deprecated, use :meth:`Series.shift` or :meth:`DataFrame.shift` instead (:issue:`37601`) - Partial slicing on unordered :class:`DatetimeIndex` with keys, which are not in Index is deprecated and will be removed in a future version (:issue:`18531`) -- Deprecated :meth:`Index.asi8` (:issue:`??`) +- Deprecated :meth:`Index.asi8` (:issue:`37877`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 24adca62b839a..77eff08350761 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -4723,7 +4723,7 @@ def argsort(self, *args, **kwargs) -> np.ndarray: Index(['a', 'b', 'c', 'd'], dtype='object') """ if needs_i8_conversion(self.dtype): - # TODO: these do not match the underlying EA argsort methods + # TODO: these do not match the underlying EA argsort methods GH#37863 return self.asi8.argsort(*args, **kwargs) # This works for either ndarray or EA, is overriden diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 22fdc31f10ae4..a10be99dff076 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -358,6 +358,7 @@ def test_ravel_deprecation(self, index): index.ravel() def test_asi8_deprecation(self, index): + # GH#37877 if isinstance( index, (Int64Index, UInt64Index, DatetimeIndex, TimedeltaIndex, PeriodIndex) ): From 8fa6a16d08bd00bd32cb82ead57a9b699d4a1681 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 17 Nov 2020 15:08:42 -0800 Subject: [PATCH 4/5] update whatsnew --- doc/source/whatsnew/v1.2.0.rst | 2 +- pandas/core/indexes/numeric.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 747c182259ae5..d0af074c6f7cd 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -458,7 +458,7 @@ Deprecations - :meth:`Categorical.is_dtype_equal` and :meth:`CategoricalIndex.is_dtype_equal` are deprecated, will be removed in a future version (:issue:`37545`) - :meth:`Series.slice_shift` and :meth:`DataFrame.slice_shift` are deprecated, use :meth:`Series.shift` or :meth:`DataFrame.shift` instead (:issue:`37601`) - Partial slicing on unordered :class:`DatetimeIndex` with keys, which are not in Index is deprecated and will be removed in a future version (:issue:`18531`) -- Deprecated :meth:`Index.asi8` (:issue:`37877`) +- Deprecated :meth:`Index.asi8` for :class:`Index` subclasses other than :class:`DatetimeIndex`, :class:`TimedeltaIndex`, and :class:`PeriodIndex` (:issue:`37877`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index 9eb8a8b719d41..9dacdd6dea9ca 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -1,5 +1,6 @@ import operator from typing import Any +import warnings import numpy as np @@ -266,6 +267,11 @@ def inferred_type(self) -> str: @property def asi8(self) -> np.ndarray: # do not cache or you'll create a memory leak + warnings.warn( + "Index.asi8 is deprecated and will be removed in a future version", + FutureWarning, + stacklevel=2, + ) return self._values.view(self._default_dtype) From 903252e4072db7e7a9d8380e1be0bc8a5e21c6c3 Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 18 Nov 2020 08:19:51 -0800 Subject: [PATCH 5/5] CLN: remove unused import --- pandas/core/indexes/period.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index d52a8ae935688..0b0f985697da9 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -6,7 +6,7 @@ from pandas._libs import index as libindex from pandas._libs.tslibs import BaseOffset, Period, Resolution, Tick from pandas._libs.tslibs.parsing import DateParseError, parse_time_string -from pandas._typing import DtypeObj, Label +from pandas._typing import DtypeObj from pandas.errors import InvalidIndexError from pandas.util._decorators import Appender, cache_readonly, doc