diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index 3dd8fd4a38d7e..a8c72ccb666a5 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -269,7 +269,7 @@ Deprecations version 1.1. All other arguments should be given as keyword arguments (:issue:`27573`). -- +- :func:`pandas.api.types.is_categorical` is deprecated and will be removed in a future version; use `:func:pandas.api.types.is_categorical_dtype` instead (:issue:`33385`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py index 16373bd697c1f..6a9ecfe709847 100644 --- a/pandas/core/dtypes/common.py +++ b/pandas/core/dtypes/common.py @@ -125,7 +125,7 @@ def ensure_categorical(arr): cat_arr : The original array cast as a Categorical. If it already is a Categorical, we return as is. """ - if not is_categorical(arr): + if not is_categorical_dtype(arr.dtype): from pandas import Categorical arr = Categorical(arr) @@ -360,6 +360,12 @@ def is_categorical(arr) -> bool: >>> is_categorical(pd.CategoricalIndex([1, 2, 3])) True """ + warnings.warn( + "is_categorical is deprecated and will be removed in a future version. " + "Use is_categorical_dtype instead", + FutureWarning, + stacklevel=2, + ) return isinstance(arr, ABCCategorical) or is_categorical_dtype(arr) @@ -1458,7 +1464,7 @@ def is_extension_type(arr) -> bool: stacklevel=2, ) - if is_categorical(arr): + if is_categorical_dtype(arr): return True elif is_sparse(arr): return True diff --git a/pandas/core/dtypes/dtypes.py b/pandas/core/dtypes/dtypes.py index 4be5da9c4c54a..8fe2b3c60d6d0 100644 --- a/pandas/core/dtypes/dtypes.py +++ b/pandas/core/dtypes/dtypes.py @@ -337,7 +337,6 @@ def _from_values_or_dtype( >>> pd.CategoricalDtype._from_values_or_dtype(c, dtype=dtype2) CategoricalDtype(categories=['x', 'y'], ordered=False) """ - from pandas.core.dtypes.common import is_categorical if dtype is not None: # The dtype argument takes precedence over values.dtype (if any) @@ -352,7 +351,7 @@ def _from_values_or_dtype( ) elif not isinstance(dtype, CategoricalDtype): raise ValueError(f"Cannot not construct CategoricalDtype from {dtype}") - elif is_categorical(values): + elif cls.is_dtype(values): # If no "dtype" was passed, use the one from "values", but honor # the "ordered" and "categories" arguments dtype = values.dtype._from_categorical_dtype( diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index d5df661efa692..18e995ce4efd7 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -20,7 +20,7 @@ ) from pandas.core.dtypes.common import ( ensure_platform_int, - is_categorical, + is_categorical_dtype, is_datetime64tz_dtype, is_datetime_or_timedelta_dtype, is_dtype_equal, @@ -787,7 +787,7 @@ def get_indexer( left_indexer = self.left.get_indexer(target_as_index.left) right_indexer = self.right.get_indexer(target_as_index.right) indexer = np.where(left_indexer == right_indexer, left_indexer, -1) - elif is_categorical(target_as_index): + elif is_categorical_dtype(target_as_index.dtype): # get an indexer for unique categories then propagate to codes via take_1d categories_indexer = self.get_indexer(target_as_index.categories) indexer = take_1d(categories_indexer, target_as_index.codes, fill_value=-1) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index ba2fd037901a2..a404c3d11723e 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -30,7 +30,6 @@ DT64NS_DTYPE, TD64NS_DTYPE, is_bool_dtype, - is_categorical, is_categorical_dtype, is_datetime64_dtype, is_datetime64tz_dtype, @@ -2764,7 +2763,7 @@ def get_block_type(values, dtype=None): if is_sparse(dtype): # Need this first(ish) so that Sparse[datetime] is sparse cls = ExtensionBlock - elif is_categorical(values): + elif is_categorical_dtype(values.dtype): cls = CategoricalBlock elif issubclass(vtype, np.datetime64): assert not is_datetime64tz_dtype(values) diff --git a/pandas/core/reshape/merge.py b/pandas/core/reshape/merge.py index 47fa0627cd1b4..607a1b75dcfcd 100644 --- a/pandas/core/reshape/merge.py +++ b/pandas/core/reshape/merge.py @@ -6,7 +6,7 @@ import datetime from functools import partial import string -from typing import TYPE_CHECKING, Optional, Tuple, Union, cast +from typing import TYPE_CHECKING, Optional, Tuple, Union import warnings import numpy as np @@ -24,7 +24,6 @@ is_array_like, is_bool, is_bool_dtype, - is_categorical, is_categorical_dtype, is_datetime64tz_dtype, is_dtype_equal, @@ -1936,9 +1935,8 @@ def _factorize_keys( elif ( is_categorical_dtype(lk) and is_categorical_dtype(rk) and is_dtype_equal(lk, rk) ): - assert is_categorical(lk) and is_categorical(rk) - lk = cast(Categorical, lk) - rk = cast(Categorical, rk) + assert isinstance(lk, Categorical) + assert isinstance(rk, Categorical) if lk.categories.equals(rk.categories): # if we exactly match in categories, allow us to factorize on codes rk = rk.codes diff --git a/pandas/tests/dtypes/test_common.py b/pandas/tests/dtypes/test_common.py index 66bf696cbe912..6e73e1542bb80 100644 --- a/pandas/tests/dtypes/test_common.py +++ b/pandas/tests/dtypes/test_common.py @@ -203,11 +203,18 @@ def test_is_scipy_sparse(): def test_is_categorical(): cat = pd.Categorical([1, 2, 3]) - assert com.is_categorical(cat) - assert com.is_categorical(pd.Series(cat)) - assert com.is_categorical(pd.CategoricalIndex([1, 2, 3])) + with tm.assert_produces_warning(FutureWarning): + assert com.is_categorical(cat) + assert com.is_categorical(pd.Series(cat)) + assert com.is_categorical(pd.CategoricalIndex([1, 2, 3])) + + assert not com.is_categorical([1, 2, 3]) - assert not com.is_categorical([1, 2, 3]) + +def test_is_categorical_deprecation(): + # GH#33385 + with tm.assert_produces_warning(FutureWarning): + com.is_categorical([1, 2, 3]) def test_is_datetime64_dtype(): diff --git a/pandas/tests/dtypes/test_dtypes.py b/pandas/tests/dtypes/test_dtypes.py index d0831ea514a64..519f2f3eead1c 100644 --- a/pandas/tests/dtypes/test_dtypes.py +++ b/pandas/tests/dtypes/test_dtypes.py @@ -159,10 +159,12 @@ def test_basic(self, dtype): assert is_categorical_dtype(s) assert not is_categorical_dtype(np.dtype("float64")) - assert is_categorical(s.dtype) - assert is_categorical(s) - assert not is_categorical(np.dtype("float64")) - assert not is_categorical(1.0) + with tm.assert_produces_warning(FutureWarning): + # GH#33385 deprecated + assert is_categorical(s.dtype) + assert is_categorical(s) + assert not is_categorical(np.dtype("float64")) + assert not is_categorical(1.0) def test_tuple_categories(self): categories = [(1, "a"), (2, "b"), (3, "c")]