diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index f2dc4c089c79f..1fdbd93572d53 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1309,6 +1309,7 @@ Deprecations - :meth:`Series.clip_lower`, :meth:`Series.clip_upper`, :meth:`DataFrame.clip_lower` and :meth:`DataFrame.clip_upper` are deprecated and will be removed in a future version. Use ``Series.clip(lower=threshold)``, ``Series.clip(upper=threshold)`` and the equivalent ``DataFrame`` methods (:issue:`24203`) - :meth:`Series.nonzero` is deprecated and will be removed in a future version (:issue:`18262`) - Passing an integer to :meth:`Series.fillna` and :meth:`DataFrame.fillna` with ``timedelta64[ns]`` dtypes is deprecated, will raise ``TypeError`` in a future version. Use ``obj.fillna(pd.Timedelta(...))`` instead (:issue:`24694`) +- ``Series.cat.categorical``, ``Series.cat.name`` and ``Sersies.cat.index`` have been deprecated. Use the attributes on ``Series.cat`` or ``Series`` directly. (:issue:`24751`). .. _whatsnew_0240.deprecations.datetimelike_int_ops: diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 1368232470402..35b662eaae9a5 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2498,8 +2498,8 @@ class CategoricalAccessor(PandasDelegate, PandasObject, NoNewAttributesMixin): def __init__(self, data): self._validate(data) self._parent = data.values - self.index = data.index - self.name = data.name + self._index = data.index + self._name = data.name self._freeze() @staticmethod @@ -2520,15 +2520,47 @@ def codes(self): Return Series of codes as well as the index. """ from pandas import Series - return Series(self._parent.codes, index=self.index) + return Series(self._parent.codes, index=self._index) def _delegate_method(self, name, *args, **kwargs): from pandas import Series method = getattr(self._parent, name) res = method(*args, **kwargs) if res is not None: - return Series(res, index=self.index, name=self.name) + return Series(res, index=self._index, name=self._name) + @property + def categorical(self): + # Note: Upon deprecation, `test_tab_completion_with_categorical` will + # need to be updated. `categorical` will need to be removed from + # `ok_for_cat`. + warn("`Series.cat.categorical` has been deprecated. Use the " + "attributes on 'Series.cat' directly instead.", + FutureWarning, + stacklevel=2) + return self._parent + + @property + def name(self): + # Note: Upon deprecation, `test_tab_completion_with_categorical` will + # need to be updated. `name` will need to be removed from + # `ok_for_cat`. + warn("`Series.cat.name` has been deprecated. Use `Series.name` " + "instead.", + FutureWarning, + stacklevel=2) + return self._name + + @property + def index(self): + # Note: Upon deprecation, `test_tab_completion_with_categorical` will + # need to be updated. `index` will need to be removed from + # ok_for_cat`. + warn("`Series.cat.index` has been deprecated. Use `Series.index` " + "instead.", + FutureWarning, + stacklevel=2) + return self._index # utility routines diff --git a/pandas/tests/arrays/categorical/test_warnings.py b/pandas/tests/arrays/categorical/test_warnings.py index 91278580254aa..23d00585f950e 100644 --- a/pandas/tests/arrays/categorical/test_warnings.py +++ b/pandas/tests/arrays/categorical/test_warnings.py @@ -2,6 +2,7 @@ import pytest +import pandas as pd import pandas.util.testing as tm @@ -16,3 +17,15 @@ def test_tab_complete_warning(self, ip): with tm.assert_produces_warning(None): with provisionalcompleter('ignore'): list(ip.Completer.completions('c.', 1)) + + def test_CategoricalAccessor_categorical_deprecation(object): + with tm.assert_produces_warning(FutureWarning): + pd.Series(['a', 'b'], dtype='category').cat.categorical + + def test_CategoricalAccessor_name_deprecation(object): + with tm.assert_produces_warning(FutureWarning): + pd.Series(['a', 'b'], dtype='category').cat.name + + def test_CategoricalAccessor_index_deprecation(object): + with tm.assert_produces_warning(FutureWarning): + pd.Series(['a', 'b'], dtype='category').cat.index diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index 09e556af883c1..c95cf125e22f7 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -245,10 +245,11 @@ def test_tab_completion(self): def test_tab_completion_with_categorical(self): # test the tab completion display - ok_for_cat = ['categories', 'codes', 'ordered', 'set_categories', - 'add_categories', 'remove_categories', - 'rename_categories', 'reorder_categories', - 'remove_unused_categories', 'as_ordered', 'as_unordered'] + ok_for_cat = ['name', 'index', 'categorical', 'categories', 'codes', + 'ordered', 'set_categories', 'add_categories', + 'remove_categories', 'rename_categories', + 'reorder_categories', 'remove_unused_categories', + 'as_ordered', 'as_unordered'] def get_dir(s): results = [r for r in s.cat.__dir__() if not r.startswith('_')] diff --git a/pandas/tests/test_config.py b/pandas/tests/test_config.py index 2cdcb948eb917..6e47f5543012f 100644 --- a/pandas/tests/test_config.py +++ b/pandas/tests/test_config.py @@ -251,7 +251,6 @@ def test_deprecate_option(self): KeyError, message="Nonexistent option didn't raise KeyError"): self.cf.get_option('foo') - assert len(w) == 1 # should have raised one warning assert 'deprecated' in str(w[-1]) # we get the default message