From 5aa07d770ac8d28510659f564215c438c7d11409 Mon Sep 17 00:00:00 2001 From: benjamin Date: Sun, 13 Jan 2019 20:42:06 +0000 Subject: [PATCH 01/12] Implementation for CategoricalAccessor.categorical removed in 0.24.0rc1 #24751 --- doc/source/whatsnew/v0.24.0.rst | 1 + pandas/core/arrays/categorical.py | 22 +++++++++++++++++-- .../tests/arrays/categorical/test_warnings.py | 13 +++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index a18739f4b26bf..3480466dfa9ba 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`) +- The ``name``, ``index`` and ``categorical`` attributes of ``CategoricalAccessor`` have been removed in 0.24.0rc1, but should be deprecated for the time being, raising an appropriate warning (:issue:`24751`). .. _whatsnew_0240.deprecations.datetimelike_int_ops: diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 1368232470402..ebed96d0b8d0d 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2498,8 +2498,6 @@ 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._freeze() @staticmethod @@ -2529,6 +2527,26 @@ def _delegate_method(self, name, *args, **kwargs): if res is not None: return Series(res, index=self.index, name=self.name) + @property + def categorical(self): + warn("s.cat.categorical has been deprecated", + DeprecationWarning, + stacklevel=2) + return self._parent + + @property + def name(self): + warn("s.cat.name has been deprecated", + DeprecationWarning, + stacklevel=2) + return self._parent + + @property + def index(self): + warn("s.cat.index has been deprecated", + DeprecationWarning, + stacklevel=2) + return self._parent # utility routines diff --git a/pandas/tests/arrays/categorical/test_warnings.py b/pandas/tests/arrays/categorical/test_warnings.py index 91278580254aa..480c5815ab641 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(DeprecationWarning): + pd.Series(['a', 'b'], dtype='category').cat.categorical.ordered + + def test_CategoricalAccessor_name_deprecation(object): + with tm.assert_produces_warning(DeprecationWarning): + pd.Series(['a', 'b'], dtype='category').cat.name + + def test_CategoricalAccessor_index_deprecation(object): + with tm.assert_produces_warning(DeprecationWarning): + pd.Series(['a', 'b'], dtype='category').cat.index From 4bba94c849e3465ff563de6e5ca5631f07e290ac Mon Sep 17 00:00:00 2001 From: benjamin Date: Sun, 13 Jan 2019 21:34:50 +0000 Subject: [PATCH 02/12] Slight tweak - was returning wrong values. --- pandas/core/arrays/categorical.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index ebed96d0b8d0d..2a1f6664f7e47 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2498,6 +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._freeze() @staticmethod @@ -2539,14 +2541,14 @@ def name(self): warn("s.cat.name has been deprecated", DeprecationWarning, stacklevel=2) - return self._parent + return self._name @property def index(self): warn("s.cat.index has been deprecated", DeprecationWarning, stacklevel=2) - return self._parent + return self._index # utility routines From dd6bf7ec5e3b972a975366d9ef2660dfd4becac1 Mon Sep 17 00:00:00 2001 From: benjamin Date: Sun, 13 Jan 2019 21:53:13 +0000 Subject: [PATCH 03/12] Update to whatsnew to better describe changes. --- doc/source/whatsnew/v0.24.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 3480466dfa9ba..063577de9f16a 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1309,7 +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`) -- The ``name``, ``index`` and ``categorical`` attributes of ``CategoricalAccessor`` have been removed in 0.24.0rc1, but should be deprecated for the time being, raising an appropriate warning (:issue:`24751`). +- :attr:``CategoricalAccessor.categorical``, :attr:``CategoricalAccessor.name`` and :attr:``CategoricalAccessor.index`` have been deprecated and replaced by private :attr:``CategoricalAccessor._parent``, :attr:``CategoricalAccessor._name`` and :attr:``CategoricalAccessor._index``, respectively. (:issue:`24751`). .. _whatsnew_0240.deprecations.datetimelike_int_ops: From 0b6812713e3d9fd5c7f8d961f426d40d355dc636 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Jan 2019 19:34:56 +0000 Subject: [PATCH 04/12] Update to whatsnew --- doc/source/whatsnew/v0.24.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 063577de9f16a..d0cb94238c6e2 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1309,7 +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`) -- :attr:``CategoricalAccessor.categorical``, :attr:``CategoricalAccessor.name`` and :attr:``CategoricalAccessor.index`` have been deprecated and replaced by private :attr:``CategoricalAccessor._parent``, :attr:``CategoricalAccessor._name`` and :attr:``CategoricalAccessor._index``, respectively. (:issue:`24751`). +- ``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: From 25067b6f5f3b10ef6be34c0f5dfb5069941a3f07 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Jan 2019 19:51:57 +0000 Subject: [PATCH 05/12] DeprecationWarning changed to FutureWarning and messages updated. --- pandas/core/arrays/categorical.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 2a1f6664f7e47..e7a7b8200cefd 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2531,22 +2531,22 @@ def _delegate_method(self, name, *args, **kwargs): @property def categorical(self): - warn("s.cat.categorical has been deprecated", - DeprecationWarning, + 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): - warn("s.cat.name has been deprecated", - DeprecationWarning, + warn("`Series.cat.name` has been deprecated. Use `Series.name` instead.", + FutureWarning, stacklevel=2) return self._name @property def index(self): - warn("s.cat.index has been deprecated", - DeprecationWarning, + warn("`Series.cat.index` has been deprecated. Use `Series.index` instead.", + FutureWarning, stacklevel=2) return self._index From fc7dcc9dbee385d85e6131b247eaa8fb15ae284d Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Jan 2019 19:54:31 +0000 Subject: [PATCH 06/12] Updated tests to reflect change to Warnings - from Deprecation to Future. --- pandas/tests/arrays/categorical/test_warnings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/tests/arrays/categorical/test_warnings.py b/pandas/tests/arrays/categorical/test_warnings.py index 480c5815ab641..23d00585f950e 100644 --- a/pandas/tests/arrays/categorical/test_warnings.py +++ b/pandas/tests/arrays/categorical/test_warnings.py @@ -19,13 +19,13 @@ def test_tab_complete_warning(self, ip): list(ip.Completer.completions('c.', 1)) def test_CategoricalAccessor_categorical_deprecation(object): - with tm.assert_produces_warning(DeprecationWarning): - pd.Series(['a', 'b'], dtype='category').cat.categorical.ordered + 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(DeprecationWarning): + 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(DeprecationWarning): + with tm.assert_produces_warning(FutureWarning): pd.Series(['a', 'b'], dtype='category').cat.index From ca6951964236c1facc6679f1e2f73aaaca6dfe19 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Jan 2019 21:38:28 +0000 Subject: [PATCH 07/12] Updated instance attributes to use private versions. --- pandas/core/arrays/categorical.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index e7a7b8200cefd..37a3ad74e2dbf 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2520,14 +2520,14 @@ 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): From e742fe4006a9a95268739ff4578ee51d178db243 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Jan 2019 22:43:17 +0000 Subject: [PATCH 08/12] Fix flake8 issues. --- pandas/core/arrays/categorical.py | 9 ++++++--- pandas/tests/series/test_api.py | 9 +++++---- pandas/tests/test_config.py | 3 ++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 37a3ad74e2dbf..f5839a82bde5e 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2531,21 +2531,24 @@ def _delegate_method(self, name, *args, **kwargs): @property def categorical(self): - warn("`Series.cat.categorical` has been deprecated. Use the attributes on 'Series.cat' directly instead.", + 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): - warn("`Series.cat.name` has been deprecated. Use `Series.name` instead.", + warn("`Series.cat.name` has been deprecated. Use `Series.name` " + "instead.", FutureWarning, stacklevel=2) return self._name @property def index(self): - warn("`Series.cat.index` has been deprecated. Use `Series.index` instead.", + warn("`Series.cat.index` has been deprecated. Use `Series.index` " + "instead.", FutureWarning, stacklevel=2) return self._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..c57ed374acd94 100644 --- a/pandas/tests/test_config.py +++ b/pandas/tests/test_config.py @@ -251,7 +251,8 @@ def test_deprecate_option(self): KeyError, message="Nonexistent option didn't raise KeyError"): self.cf.get_option('foo') - + for wa in w: + print(wa, wa.source, wa.line, wa.lineno) assert len(w) == 1 # should have raised one warning assert 'deprecated' in str(w[-1]) # we get the default message From 6fba2491dcc4ea2be00f061c07dc0587a431e286 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 14 Jan 2019 23:12:03 +0000 Subject: [PATCH 09/12] Removal of debugging print statement. --- pandas/tests/test_config.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandas/tests/test_config.py b/pandas/tests/test_config.py index c57ed374acd94..6e47f5543012f 100644 --- a/pandas/tests/test_config.py +++ b/pandas/tests/test_config.py @@ -251,8 +251,6 @@ def test_deprecate_option(self): KeyError, message="Nonexistent option didn't raise KeyError"): self.cf.get_option('foo') - for wa in w: - print(wa, wa.source, wa.line, wa.lineno) assert len(w) == 1 # should have raised one warning assert 'deprecated' in str(w[-1]) # we get the default message From 9a0c381cd1976dcc32ea4c1b94146fabcc0d9a48 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 15 Jan 2019 17:50:11 +0000 Subject: [PATCH 10/12] Added notes to indicate a test update required upon deprecation. --- pandas/core/arrays/categorical.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index f5839a82bde5e..f60358c29af02 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2531,6 +2531,11 @@ def _delegate_method(self, name, *args, **kwargs): @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, @@ -2539,6 +2544,11 @@ def categorical(self): @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, @@ -2547,6 +2557,11 @@ def name(self): @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, From 1e22cbb2ae192fa0ffe3abe248aea8851f5e7a66 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 15 Jan 2019 17:52:10 +0000 Subject: [PATCH 11/12] Fixed typos. --- pandas/core/arrays/categorical.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index f60358c29af02..127dcc652fea1 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2547,7 +2547,7 @@ 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`. + `ok_for_cat`. """ warn("`Series.cat.name` has been deprecated. Use `Series.name` " "instead.", @@ -2559,8 +2559,8 @@ def name(self): 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`. + 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.", From e4bb4c1a6d5adbed402417513962d723c0ecb303 Mon Sep 17 00:00:00 2001 From: benjamin Date: Tue, 15 Jan 2019 20:22:49 +0000 Subject: [PATCH 12/12] Triple quoted strs to comments, to prevent users viewing as docstrings. --- pandas/core/arrays/categorical.py | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 127dcc652fea1..35b662eaae9a5 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -2531,11 +2531,9 @@ def _delegate_method(self, name, *args, **kwargs): @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`. - """ + # 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, @@ -2544,11 +2542,9 @@ def categorical(self): @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`. - """ + # 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, @@ -2557,11 +2553,9 @@ def name(self): @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`. - """ + # 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,