diff --git a/doc/source/user_guide/categorical.rst b/doc/source/user_guide/categorical.rst index fba41f73ba819..f65638cd78a2b 100644 --- a/doc/source/user_guide/categorical.rst +++ b/doc/source/user_guide/categorical.rst @@ -954,6 +954,7 @@ categorical (categories and ordering). So if you read back the CSV file you have relevant columns back to ``category`` and assign the right categories and categories ordering. .. ipython:: python + :okwarning: import io diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 61bea198e42db..320912ec38890 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -639,7 +639,7 @@ Deprecations - Deprecated using :func:`merge` or :func:`join` on a different number of levels (:issue:`34862`) - Deprecated the use of ``**kwargs`` in :class:`.ExcelWriter`; use the keyword argument ``engine_kwargs`` instead (:issue:`40430`) - Deprecated the ``level`` keyword for :class:`DataFrame` and :class:`Series` aggregations; use groupby instead (:issue:`39983`) -- The ``inplace`` parameter of :meth:`Categorical.remove_categories`, :meth:`Categorical.add_categories`, :meth:`Categorical.reorder_categories`, :meth:`Categorical.rename_categories` is deprecated and will be removed in a future version (:issue:`37643`) +- The ``inplace`` parameter of :meth:`Categorical.remove_categories`, :meth:`Categorical.add_categories`, :meth:`Categorical.reorder_categories`, :meth:`Categorical.rename_categories`, :meth:`Categorical.set_categories` is deprecated and will be removed in a future version (:issue:`37643`) - Deprecated :func:`merge` producing duplicated columns through the ``suffixes`` keyword and already existing columns (:issue:`22818`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 7cddfef3d4292..7b653bf84a466 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -882,7 +882,9 @@ def as_unordered(self, inplace=False): inplace = validate_bool_kwarg(inplace, "inplace") return self.set_ordered(False, inplace=inplace) - def set_categories(self, new_categories, ordered=None, rename=False, inplace=False): + def set_categories( + self, new_categories, ordered=None, rename=False, inplace=no_default + ): """ Set the categories to the specified new_categories. @@ -916,6 +918,8 @@ def set_categories(self, new_categories, ordered=None, rename=False, inplace=Fal Whether or not to reorder the categories in-place or return a copy of this categorical with reordered categories. + .. deprecated:: 1.3.0 + Returns ------- Categorical with reordered categories or None if inplace. @@ -933,6 +937,18 @@ def set_categories(self, new_categories, ordered=None, rename=False, inplace=Fal remove_categories : Remove the specified categories. remove_unused_categories : Remove categories which are not used. """ + if inplace is not no_default: + warn( + "The `inplace` parameter in pandas.Categorical." + "set_categories is deprecated and will be removed in " + "a future version. Removing unused categories will always " + "return a new Categorical object.", + FutureWarning, + stacklevel=2, + ) + else: + inplace = False + inplace = validate_bool_kwarg(inplace, "inplace") if ordered is None: ordered = self.dtype.ordered @@ -1101,7 +1117,10 @@ def reorder_categories(self, new_categories, ordered=None, inplace=no_default): raise ValueError( "items in new_categories are not the same as in old categories" ) - return self.set_categories(new_categories, ordered=ordered, inplace=inplace) + + with catch_warnings(): + simplefilter("ignore") + return self.set_categories(new_categories, ordered=ordered, inplace=inplace) def add_categories(self, new_categories, inplace=no_default): """ @@ -1231,9 +1250,11 @@ def remove_categories(self, removals, inplace=no_default): if len(not_included) != 0: raise ValueError(f"removals must all be in old categories: {not_included}") - return self.set_categories( - new_categories, ordered=self.ordered, rename=False, inplace=inplace - ) + with catch_warnings(): + simplefilter("ignore") + return self.set_categories( + new_categories, ordered=self.ordered, rename=False, inplace=inplace + ) def remove_unused_categories(self, inplace=no_default): """ diff --git a/pandas/tests/arrays/categorical/test_analytics.py b/pandas/tests/arrays/categorical/test_analytics.py index 7bb86987456f1..c0287df1694e9 100644 --- a/pandas/tests/arrays/categorical/test_analytics.py +++ b/pandas/tests/arrays/categorical/test_analytics.py @@ -314,7 +314,9 @@ def test_validate_inplace_raises(self, value): cat.as_unordered(inplace=value) with pytest.raises(ValueError, match=msg): - cat.set_categories(["X", "Y", "Z"], rename=True, inplace=value) + with tm.assert_produces_warning(FutureWarning): + # issue #37643 inplace kwarg deprecated + cat.set_categories(["X", "Y", "Z"], rename=True, inplace=value) with pytest.raises(ValueError, match=msg): with tm.assert_produces_warning(FutureWarning): diff --git a/pandas/tests/arrays/categorical/test_api.py b/pandas/tests/arrays/categorical/test_api.py index 10e29dc82c050..a063491cd08fa 100644 --- a/pandas/tests/arrays/categorical/test_api.py +++ b/pandas/tests/arrays/categorical/test_api.py @@ -229,7 +229,10 @@ def test_set_categories(self): exp_categories = Index(["c", "b", "a"]) exp_values = np.array(["a", "b", "c", "a"], dtype=np.object_) - res = cat.set_categories(["c", "b", "a"], inplace=True) + with tm.assert_produces_warning(FutureWarning): + # issue #37643 inplace kwarg deprecated + res = cat.set_categories(["c", "b", "a"], inplace=True) + tm.assert_index_equal(cat.categories, exp_categories) tm.assert_numpy_array_equal(cat.__array__(), exp_values) assert res is None @@ -439,7 +442,11 @@ def test_describe(self): # check unused categories cat = self.factor.copy() - cat.set_categories(["a", "b", "c", "d"], inplace=True) + + with tm.assert_produces_warning(FutureWarning): + # issue #37643 inplace kwarg deprecated + cat.set_categories(["a", "b", "c", "d"], inplace=True) + desc = cat.describe() exp_index = CategoricalIndex( @@ -475,7 +482,11 @@ def test_describe(self): def test_set_categories_inplace(self): cat = self.factor.copy() - cat.set_categories(["a", "b", "c", "d"], inplace=True) + + with tm.assert_produces_warning(FutureWarning): + # issue #37643 inplace kwarg deprecated + cat.set_categories(["a", "b", "c", "d"], inplace=True) + tm.assert_index_equal(cat.categories, Index(["a", "b", "c", "d"])) diff --git a/pandas/tests/frame/indexing/test_setitem.py b/pandas/tests/frame/indexing/test_setitem.py index 4004e595c832f..204c7648ac2f7 100644 --- a/pandas/tests/frame/indexing/test_setitem.py +++ b/pandas/tests/frame/indexing/test_setitem.py @@ -887,9 +887,11 @@ def test_setitem_mask_categorical(self): df = DataFrame({"cats": catsf, "values": valuesf}, index=idxf) exp_fancy = exp_multi_row.copy() - return_value = exp_fancy["cats"].cat.set_categories( - ["a", "b", "c"], inplace=True - ) + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + # issue #37643 inplace kwarg deprecated + return_value = exp_fancy["cats"].cat.set_categories( + ["a", "b", "c"], inplace=True + ) assert return_value is None mask = df["cats"] == "c" diff --git a/pandas/tests/series/accessors/test_cat_accessor.py b/pandas/tests/series/accessors/test_cat_accessor.py index 8a4c4d56e264d..7aea45755f940 100644 --- a/pandas/tests/series/accessors/test_cat_accessor.py +++ b/pandas/tests/series/accessors/test_cat_accessor.py @@ -48,7 +48,11 @@ def test_cat_accessor(self): assert not ser.cat.ordered, False exp = Categorical(["a", "b", np.nan, "a"], categories=["b", "a"]) - return_value = ser.cat.set_categories(["b", "a"], inplace=True) + + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + # issue #37643 inplace kwarg deprecated + return_value = ser.cat.set_categories(["b", "a"], inplace=True) + assert return_value is None tm.assert_categorical_equal(ser.values, exp)