From 3fbeaccab43e228f54860b65a83542a3acd908fb Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 20 Oct 2022 16:23:52 -0700 Subject: [PATCH 1/2] DEPR: Categorical, Index --- doc/redirects.csv | 3 - doc/source/reference/index.rst | 2 - doc/source/reference/indexing.rst | 1 - doc/source/whatsnew/v2.0.0.rst | 8 ++ pandas/conftest.py | 1 - pandas/core/arrays/categorical.py | 41 ---------- pandas/core/indexes/base.py | 74 ------------------- pandas/core/indexes/category.py | 11 --- pandas/core/indexes/datetimelike.py | 11 --- pandas/tests/arrays/categorical/test_api.py | 6 -- .../tests/arrays/categorical/test_dtypes.py | 7 -- pandas/tests/arrays/categorical/test_take.py | 14 +--- pandas/tests/indexes/test_any_index.py | 14 ---- pandas/tests/indexes/test_common.py | 11 --- 14 files changed, 9 insertions(+), 195 deletions(-) diff --git a/doc/redirects.csv b/doc/redirects.csv index 6a79ed5958089..42f91a8b9884f 100644 --- a/doc/redirects.csv +++ b/doc/redirects.csv @@ -637,7 +637,6 @@ generated/pandas.Index.argmax,../reference/api/pandas.Index.argmax generated/pandas.Index.argmin,../reference/api/pandas.Index.argmin generated/pandas.Index.argsort,../reference/api/pandas.Index.argsort generated/pandas.Index.array,../reference/api/pandas.Index.array -generated/pandas.Index.asi8,../reference/api/pandas.Index.asi8 generated/pandas.Index.asof,../reference/api/pandas.Index.asof generated/pandas.Index.asof_locs,../reference/api/pandas.Index.asof_locs generated/pandas.Index.astype,../reference/api/pandas.Index.astype @@ -680,7 +679,6 @@ generated/pandas.Index.isin,../reference/api/pandas.Index.isin generated/pandas.Index.is_integer,../reference/api/pandas.Index.is_integer generated/pandas.Index.is_interval,../reference/api/pandas.Index.is_interval generated/pandas.Index.is_lexsorted_for_tuple,../reference/api/pandas.Index.is_lexsorted_for_tuple -generated/pandas.Index.is_mixed,../reference/api/pandas.Index.is_mixed generated/pandas.Index.is_monotonic_decreasing,../reference/api/pandas.Index.is_monotonic_decreasing generated/pandas.Index.is_monotonic,../reference/api/pandas.Index.is_monotonic generated/pandas.Index.is_monotonic_increasing,../reference/api/pandas.Index.is_monotonic_increasing @@ -688,7 +686,6 @@ generated/pandas.Index.isna,../reference/api/pandas.Index.isna generated/pandas.Index.isnull,../reference/api/pandas.Index.isnull generated/pandas.Index.is_numeric,../reference/api/pandas.Index.is_numeric generated/pandas.Index.is_object,../reference/api/pandas.Index.is_object -generated/pandas.Index.is_type_compatible,../reference/api/pandas.Index.is_type_compatible generated/pandas.Index.is_unique,../reference/api/pandas.Index.is_unique generated/pandas.Index.item,../reference/api/pandas.Index.item generated/pandas.Index.join,../reference/api/pandas.Index.join diff --git a/doc/source/reference/index.rst b/doc/source/reference/index.rst index fc920db671ee5..37cb6767f760e 100644 --- a/doc/source/reference/index.rst +++ b/doc/source/reference/index.rst @@ -47,9 +47,7 @@ public functions related to data types in pandas. .. .. toctree:: - api/pandas.Index.asi8 api/pandas.Index.holds_integer - api/pandas.Index.is_type_compatible api/pandas.Index.nlevels api/pandas.Index.sort diff --git a/doc/source/reference/indexing.rst b/doc/source/reference/indexing.rst index 533f4ee19f83b..a52ee92ea5921 100644 --- a/doc/source/reference/indexing.rst +++ b/doc/source/reference/indexing.rst @@ -68,7 +68,6 @@ Modifying and computations Index.is_floating Index.is_integer Index.is_interval - Index.is_mixed Index.is_numeric Index.is_object Index.min diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 4ac737bb6b29a..4676c9f917253 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -146,6 +146,14 @@ Deprecations Removal of prior version deprecations/changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- Removed deprecated :meth:`Categorical.to_dense`, use ``np.asarray(cat)`` instead (:issue:`32639`) +- Removed deprecated :meth:`Categorical.take_nd` (:issue:`27745`) +- Removed deprecated :meth:`Categorical.mode`, use ``Series(cat).mode()`` instead (:issue:`45033`) +- Removed deprecated :meth:`Categorical.is_dtype_equal` and :meth:`CategoricalIndex.is_dtype_equal` (:issue:`37545`) +- Removed deprecated :meth:`CategoricalIndex.take_nd` (:issue:`30702`) +- Removed deprecated :meth:`Index.is_type_compatible` (:issue:`42113`) +- Removed deprecated :meth:`Index.is_mixed`, check ``index.inferred_type`` directly instead (:issue:`32922`) +- Removed deprecated :meth:`Index.asi8` (:issue:`37877`) - Enforced deprecation disallowing passing a timezone-aware :class:`Timestamp` and ``dtype="datetime64[ns]"`` to :class:`Series` or :class:`DataFrame` constructors (:issue:`41555`) - Enforced deprecation disallowing passing a sequence of timezone-aware values and ``dtype="datetime64[ns]"`` to to :class:`Series` or :class:`DataFrame` constructors (:issue:`41555`) - Removed Date parser functions :func:`~pandas.io.date_converters.parse_date_time`, diff --git a/pandas/conftest.py b/pandas/conftest.py index e8f982949677c..074b6068a4518 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -155,7 +155,6 @@ def pytest_collection_modifyitems(items, config) -> None: ("Series.append", "The series.append method is deprecated"), ("dtypes.common.is_categorical", "is_categorical is deprecated"), ("Categorical.replace", "Categorical.replace is deprecated"), - ("Index.is_mixed", "Index.is_mixed is deprecated"), ("MultiIndex._is_lexsorted", "MultiIndex.is_lexsorted is deprecated"), # Docstring divides by zero to show behavior difference ("missing.mask_zero_div_zero", "divide by zero encountered"), diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 5a1d812cda53c..164dc74836508 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2052,24 +2052,6 @@ def _values_for_rank(self): ) return values - def to_dense(self) -> np.ndarray: - """ - Return my 'dense' representation - - For internal compatibility with numpy arrays. - - Returns - ------- - dense : array - """ - warn( - "Categorical.to_dense is deprecated and will be removed in " - "a future version. Use np.asarray(cat) instead.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return np.asarray(self) - # ------------------------------------------------------------------ # NDArrayBackedExtensionArray compat @@ -2101,17 +2083,6 @@ def _unbox_scalar(self, key) -> int: # ------------------------------------------------------------------ - def take_nd( - self, indexer, allow_fill: bool = False, fill_value=None - ) -> Categorical: - # GH#27745 deprecate alias that other EAs dont have - warn( - "Categorical.take_nd is deprecated, use Categorical.take instead", - FutureWarning, - stacklevel=find_stack_level(), - ) - return self.take(indexer, allow_fill=allow_fill, fill_value=fill_value) - def __iter__(self) -> Iterator: """ Returns an Iterator over the values of this Categorical. @@ -2539,18 +2510,6 @@ def _categories_match_up_to_permutation(self, other: Categorical) -> bool: """ return hash(self.dtype) == hash(other.dtype) - def is_dtype_equal(self, other) -> bool: - warn( - "Categorical.is_dtype_equal is deprecated and will be removed " - "in a future version", - FutureWarning, - stacklevel=find_stack_level(), - ) - try: - return self._categories_match_up_to_permutation(other) - except (AttributeError, TypeError): - return False - def describe(self) -> DataFrame: """ Describes this Categorical diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 1ae5b97cc0913..9d694face3941 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -680,23 +680,6 @@ def _dtype_to_subclass(cls, dtype: DtypeObj): See each method's docstring. """ - @property - def asi8(self): - """ - Integer representation of the values. - - Returns - ------- - ndarray - An ndarray with int64 dtype. - """ - warnings.warn( - "Index.asi8 is deprecated and will be removed in a future version.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return None - @classmethod def _simple_new(cls: type[_IndexT], values, name: Hashable = None) -> _IndexT: """ @@ -2451,7 +2434,6 @@ def is_boolean(self) -> bool: is_object : Check if the Index is of the object dtype. is_categorical : Check if the Index holds categorical data. is_interval : Check if the Index holds Interval objects. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2487,7 +2469,6 @@ def is_integer(self) -> bool: is_object : Check if the Index is of the object dtype. is_categorical : Check if the Index holds categorical data. is_interval : Check if the Index holds Interval objects. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2527,7 +2508,6 @@ def is_floating(self) -> bool: is_object : Check if the Index is of the object dtype. is_categorical : Check if the Index holds categorical data. is_interval : Check if the Index holds Interval objects. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2567,7 +2547,6 @@ def is_numeric(self) -> bool: is_object : Check if the Index is of the object dtype. is_categorical : Check if the Index holds categorical data. is_interval : Check if the Index holds Interval objects. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2611,7 +2590,6 @@ def is_object(self) -> bool: is_numeric : Check if the Index only consists of numeric data. is_categorical : Check if the Index holds categorical data. is_interval : Check if the Index holds Interval objects. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2653,7 +2631,6 @@ def is_categorical(self) -> bool: is_numeric : Check if the Index only consists of numeric data. is_object : Check if the Index is of the object dtype. is_interval : Check if the Index holds Interval objects. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2697,7 +2674,6 @@ def is_interval(self) -> bool: is_numeric : Check if the Index only consists of numeric data. is_object : Check if the Index is of the object dtype. is_categorical : Check if the Index holds categorical data. - is_mixed : Check if the Index holds data with mixed data types. Examples -------- @@ -2712,44 +2688,6 @@ def is_interval(self) -> bool: """ return self.inferred_type in ["interval"] - @final - def is_mixed(self) -> bool: - """ - Check if the Index holds data with mixed data types. - - Returns - ------- - bool - Whether or not the Index holds data with mixed data types. - - See Also - -------- - is_boolean : Check if the Index only consists of booleans. - is_integer : Check if the Index only consists of integers. - is_floating : Check if the Index is a floating type. - is_numeric : Check if the Index only consists of numeric data. - is_object : Check if the Index is of the object dtype. - is_categorical : Check if the Index holds categorical data. - is_interval : Check if the Index holds Interval objects. - - Examples - -------- - >>> idx = pd.Index(['a', np.nan, 'b']) - >>> idx.is_mixed() - True - - >>> idx = pd.Index([1.0, 2.0, 3.0, 5.0]) - >>> idx.is_mixed() - False - """ - warnings.warn( - "Index.is_mixed is deprecated and will be removed in a future version. " - "Check index.inferred_type directly instead.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return self.inferred_type in ["mixed"] - @final def holds_integer(self) -> bool: """ @@ -5312,18 +5250,6 @@ def _is_memory_usage_qualified(self) -> bool: """ return self.is_object() - def is_type_compatible(self, kind: str_t) -> bool: - """ - Whether the index type is compatible with the provided type. - """ - warnings.warn( - "Index.is_type_compatible is deprecated and will be removed in a " - "future version.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return kind == self.inferred_type - def __contains__(self, key: Any) -> bool: """ Return a boolean indicating whether the provided key is in the index. diff --git a/pandas/core/indexes/category.py b/pandas/core/indexes/category.py index baa938a6f7646..58b533cb576d9 100644 --- a/pandas/core/indexes/category.py +++ b/pandas/core/indexes/category.py @@ -61,7 +61,6 @@ "ordered", "_reverse_indexer", "searchsorted", - "is_dtype_equal", "min", "max", ], @@ -489,16 +488,6 @@ def _maybe_cast_listlike_indexer(self, values) -> CategoricalIndex: def _is_comparable_dtype(self, dtype: DtypeObj) -> bool: return self.categories._is_comparable_dtype(dtype) - def take_nd(self, *args, **kwargs) -> CategoricalIndex: - """Alias for `take`""" - warnings.warn( - "CategoricalIndex.take_nd is deprecated, use CategoricalIndex.take " - "instead.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return self.take(*args, **kwargs) - def map(self, mapper): """ Map values using input an input mapping or function. diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index dafa5e9680eec..db32bf3d9f542 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -13,7 +13,6 @@ cast, final, ) -import warnings import numpy as np @@ -36,7 +35,6 @@ cache_readonly, doc, ) -from pandas.util._exceptions import find_stack_level from pandas.core.dtypes.common import ( is_categorical_dtype, @@ -394,15 +392,6 @@ def _with_freq(self, freq): arr = self._data._with_freq(freq) return type(self)._simple_new(arr, name=self._name) - def is_type_compatible(self, kind: str) -> bool: - warnings.warn( - f"{type(self).__name__}.is_type_compatible is deprecated and will be " - "removed in a future version.", - FutureWarning, - stacklevel=find_stack_level(), - ) - return kind in self._data._infer_matches - @property def values(self) -> np.ndarray: # NB: For Datetime64TZ this is lossy diff --git a/pandas/tests/arrays/categorical/test_api.py b/pandas/tests/arrays/categorical/test_api.py index 377ab530d8733..e3fd73aaa9b1c 100644 --- a/pandas/tests/arrays/categorical/test_api.py +++ b/pandas/tests/arrays/categorical/test_api.py @@ -330,12 +330,6 @@ def test_set_categories(self): tm.assert_numpy_array_equal(np.asarray(c), np.asarray(c2)) - def test_to_dense_deprecated(self): - cat = Categorical(["a", "b", "c", "a"], ordered=True) - - with tm.assert_produces_warning(FutureWarning): - cat.to_dense() - @pytest.mark.parametrize( "values, categories, new_categories", [ diff --git a/pandas/tests/arrays/categorical/test_dtypes.py b/pandas/tests/arrays/categorical/test_dtypes.py index ddaf6aa46bc4f..7447daadbdd48 100644 --- a/pandas/tests/arrays/categorical/test_dtypes.py +++ b/pandas/tests/arrays/categorical/test_dtypes.py @@ -15,13 +15,6 @@ class TestCategoricalDtypes: - def test_is_dtype_equal_deprecated(self): - # GH#37545 - c1 = Categorical(list("aabca"), categories=list("abc"), ordered=False) - - with tm.assert_produces_warning(FutureWarning): - c1.is_dtype_equal(c1) - def test_categories_match_up_to_permutation(self): # test dtype comparisons between cats diff --git a/pandas/tests/arrays/categorical/test_take.py b/pandas/tests/arrays/categorical/test_take.py index fbdbea1dae3b2..fb79fe4923522 100644 --- a/pandas/tests/arrays/categorical/test_take.py +++ b/pandas/tests/arrays/categorical/test_take.py @@ -1,10 +1,7 @@ import numpy as np import pytest -from pandas import ( - Categorical, - Index, -) +from pandas import Categorical import pandas._testing as tm @@ -84,12 +81,3 @@ def test_take_fill_value_new_raises(self): xpr = r"Cannot setitem on a Categorical with a new category \(d\)" with pytest.raises(TypeError, match=xpr): cat.take([0, 1, -1], fill_value="d", allow_fill=True) - - def test_take_nd_deprecated(self): - cat = Categorical(["a", "b", "c"]) - with tm.assert_produces_warning(FutureWarning): - cat.take_nd([0, 1]) - - ci = Index(cat) - with tm.assert_produces_warning(FutureWarning): - ci.take_nd([0, 1]) diff --git a/pandas/tests/indexes/test_any_index.py b/pandas/tests/indexes/test_any_index.py index 1745e5680c721..6868279776a91 100644 --- a/pandas/tests/indexes/test_any_index.py +++ b/pandas/tests/indexes/test_any_index.py @@ -67,20 +67,6 @@ def test_ravel_deprecation(index): index.ravel() -def test_is_type_compatible_deprecation(index): - # GH#42113 - msg = "is_type_compatible is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): - index.is_type_compatible(index.inferred_type) - - -def test_is_mixed_deprecated(index): - # GH#32922 - msg = "Index.is_mixed is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): - index.is_mixed() - - class TestConversion: def test_to_series(self, index): # assert that we are creating a copy of the index diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 8635aed3559d4..834be77cbdcda 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -23,7 +23,6 @@ MultiIndex, PeriodIndex, RangeIndex, - TimedeltaIndex, ) import pandas._testing as tm from pandas.core.api import NumericIndex @@ -423,16 +422,6 @@ def test_astype_preserves_name(self, index, dtype): else: assert result.name == index.name - def test_asi8_deprecation(self, index): - # GH#37877 - if isinstance(index, (DatetimeIndex, TimedeltaIndex, PeriodIndex)): - warn = None - else: - warn = FutureWarning - - with tm.assert_produces_warning(warn): - index.asi8 - def test_hasnans_isnans(self, index_flat): # GH#11343, added tests for hasnans / isnans index = index_flat From 2afc8acd94fce193535924c3f8026a65c68f23ee Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 20 Oct 2022 20:17:14 -0700 Subject: [PATCH 2/2] mypy fixup --- pandas/core/indexes/datetimelike.py | 11 +++++++++-- pandas/core/indexes/period.py | 2 +- pandas/core/tools/numeric.py | 2 +- pandas/core/window/rolling.py | 4 +++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index db32bf3d9f542..63acb2ab24422 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -28,7 +28,10 @@ parsing, to_offset, ) -from pandas._typing import Axis +from pandas._typing import ( + Axis, + npt, +) from pandas.compat.numpy import function as nv from pandas.util._decorators import ( Appender, @@ -78,7 +81,7 @@ DatetimeLikeArrayMixin, cache=True, ) -@inherit_names(["mean", "asi8", "freq", "freqstr"], DatetimeLikeArrayMixin) +@inherit_names(["mean", "freq", "freqstr"], DatetimeLikeArrayMixin) class DatetimeIndexOpsMixin(NDArrayBackedExtensionIndex): """ Common ops mixin to support a unified interface datetimelike Index. @@ -91,6 +94,10 @@ class DatetimeIndexOpsMixin(NDArrayBackedExtensionIndex): freqstr: str | None _resolution_obj: Resolution + @property + def asi8(self) -> npt.NDArray[np.int64]: + return self._data.asi8 + # ------------------------------------------------------------------------ @cache_readonly diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index a5408f19456dd..32f6fe06f3587 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -386,7 +386,7 @@ def is_full(self) -> bool: if not self.is_monotonic_increasing: raise ValueError("Index is not monotonic") values = self.asi8 - return ((values[1:] - values[:-1]) < 2).all() + return bool(((values[1:] - values[:-1]) < 2).all()) @property def inferred_type(self) -> str: diff --git a/pandas/core/tools/numeric.py b/pandas/core/tools/numeric.py index 9b158a6b5aed2..da47aa549dfa3 100644 --- a/pandas/core/tools/numeric.py +++ b/pandas/core/tools/numeric.py @@ -158,7 +158,7 @@ def to_numeric( elif isinstance(arg, ABCIndex): is_index = True if needs_i8_conversion(arg.dtype): - values = arg.asi8 + values = arg.view("i8") else: values = arg.values elif isinstance(arg, (list, tuple)): diff --git a/pandas/core/window/rolling.py b/pandas/core/window/rolling.py index 80b782d582561..139909a77f94a 100644 --- a/pandas/core/window/rolling.py +++ b/pandas/core/window/rolling.py @@ -16,6 +16,7 @@ Hashable, Iterator, Sized, + cast, ) import warnings @@ -442,7 +443,8 @@ def _insert_on_column(self, result: DataFrame, obj: DataFrame) -> None: 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 + idx = cast("PeriodIndex | DatetimeIndex | TimedeltaIndex", self._on) + return idx.asi8 return None def _resolve_output(self, out: DataFrame, obj: DataFrame) -> DataFrame: