From 4d12bc2227db9b51d037dc584dee92908ac20e30 Mon Sep 17 00:00:00 2001 From: Luke Manley Date: Tue, 1 Nov 2022 19:26:04 -0400 Subject: [PATCH 1/2] enforce deprecation of inplace argument in set_axis --- doc/source/whatsnew/v2.0.0.rst | 1 + pandas/core/frame.py | 36 +---------- pandas/core/generic.py | 63 ++----------------- pandas/core/series.py | 36 +---------- pandas/tests/frame/methods/test_set_axis.py | 53 +++------------- pandas/tests/generic/test_duplicate_labels.py | 13 +--- 6 files changed, 17 insertions(+), 185 deletions(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 5614b7a2c0846..45917f14c8249 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -185,6 +185,7 @@ Removal of prior version deprecations/changes - Removed ``keep_tz`` argument in :meth:`DatetimeIndex.to_series` (:issue:`29731`) - Remove arguments ``names`` and ``dtype`` from :meth:`Index.copy` and ``levels`` and ``codes`` from :meth:`MultiIndex.copy` (:issue:`35853`, :issue:`36685`) - Remove argument ``inplace`` from :meth:`MultiIndex.set_levels` and :meth:`MultiIndex.set_codes` (:issue:`35626`) +- Removed argument ``inplace`` from :meth:`DataFrame.set_axis` and :meth:`Series.set_axis`, use ``obj = obj.set_axis(..., copy=False)`` instead (:issue:`48130`) - Disallow passing positional arguments to :meth:`MultiIndex.set_levels` and :meth:`MultiIndex.set_codes` (:issue:`41485`) - Removed :meth:`MultiIndex.is_lexsorted` and :meth:`MultiIndex.lexsort_depth` (:issue:`38701`) - Removed argument ``how`` from :meth:`PeriodIndex.astype`, use :meth:`PeriodIndex.to_timestamp` instead (:issue:`37982`) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 17c4bde9d0279..b45e3ba93181b 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -5057,39 +5057,6 @@ def align( broadcast_axis=broadcast_axis, ) - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: Literal[False] | lib.NoDefault = ..., - copy: bool | lib.NoDefault = ..., - ) -> DataFrame: - ... - - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: Literal[True], - copy: bool | lib.NoDefault = ..., - ) -> None: - ... - - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: bool | lib.NoDefault = ..., - copy: bool | lib.NoDefault = ..., - ) -> DataFrame | None: - ... - # error: Signature of "set_axis" incompatible with supertype "NDFrame" @Appender( """ @@ -5134,10 +5101,9 @@ def set_axis( labels, *, axis: Axis = 0, - inplace: bool | lib.NoDefault = lib.no_default, copy: bool | lib.NoDefault = lib.no_default, ): - return super().set_axis(labels, axis=axis, inplace=inplace, copy=copy) + return super().set_axis(labels, axis=axis, copy=copy) @Substitution(**_shared_doc_kwargs) @Appender(NDFrame.reindex.__doc__) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 8bf3820d2ea3c..603d5376e824f 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -698,45 +698,11 @@ def size(self) -> int: # expected "int") [return-value] return np.prod(self.shape) # type: ignore[return-value] - @overload - def set_axis( - self: NDFrameT, - labels, - *, - axis: Axis = ..., - inplace: Literal[False] | lib.NoDefault = ..., - copy: bool_t | lib.NoDefault = ..., - ) -> NDFrameT: - ... - - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: Literal[True], - copy: bool_t | lib.NoDefault = ..., - ) -> None: - ... - - @overload - def set_axis( - self: NDFrameT, - labels, - *, - axis: Axis = ..., - inplace: bool_t | lib.NoDefault = ..., - copy: bool_t | lib.NoDefault = ..., - ) -> NDFrameT | None: - ... - def set_axis( self: NDFrameT, labels, *, axis: Axis = 0, - inplace: bool_t | lib.NoDefault = lib.no_default, copy: bool_t | lib.NoDefault = lib.no_default, ) -> NDFrameT | None: """ @@ -754,11 +720,6 @@ def set_axis( The axis to update. The value 0 identifies the rows. For `Series` this parameter is unused and defaults to 0. - inplace : bool, default False - Whether to return a new %(klass)s instance. - - .. deprecated:: 1.5.0 - copy : bool, default True Whether to make a copy of the underlying data. @@ -766,33 +727,17 @@ def set_axis( Returns ------- - renamed : %(klass)s or None - An object of type %(klass)s or None if ``inplace=True``. + renamed : %(klass)s + An object of type %(klass)s. See Also -------- %(klass)s.rename_axis : Alter the name of the index%(see_also_sub)s. """ - if inplace is not lib.no_default: - warnings.warn( - f"{type(self).__name__}.set_axis 'inplace' keyword is deprecated " - "and will be removed in a future version. Use " - "`obj = obj.set_axis(..., copy=False)` instead", - FutureWarning, - stacklevel=find_stack_level(), - ) - else: - inplace = False - - if inplace: - if copy is True: - raise ValueError("Cannot specify both inplace=True and copy=True") - copy = False - elif copy is lib.no_default: + if copy is lib.no_default: copy = True - self._check_inplace_and_allows_duplicate_labels(inplace) - return self._set_axis_nocheck(labels, axis, inplace, copy=copy) + return self._set_axis_nocheck(labels, axis, inplace=False, copy=copy) @final def _set_axis_nocheck(self, labels, axis: Axis, inplace: bool_t, copy: bool_t): diff --git a/pandas/core/series.py b/pandas/core/series.py index 7854bf6180733..4037d16d36920 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -4942,39 +4942,6 @@ def rename( else: return self._set_name(index, inplace=inplace) - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: Literal[False] | lib.NoDefault = ..., - copy: bool | lib.NoDefault = ..., - ) -> Series: - ... - - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: Literal[True], - copy: bool | lib.NoDefault = ..., - ) -> None: - ... - - @overload - def set_axis( - self, - labels, - *, - axis: Axis = ..., - inplace: bool | lib.NoDefault = ..., - copy: bool | lib.NoDefault = ..., - ) -> Series | None: - ... - # error: Signature of "set_axis" incompatible with supertype "NDFrame" @Appender( """ @@ -5006,10 +4973,9 @@ def set_axis( # type: ignore[override] labels, *, axis: Axis = 0, - inplace: bool | lib.NoDefault = lib.no_default, copy: bool | lib.NoDefault = lib.no_default, ) -> Series | None: - return super().set_axis(labels, axis=axis, inplace=inplace, copy=copy) + return super().set_axis(labels, axis=axis, copy=copy) # error: Cannot determine type of 'reindex' @doc( diff --git a/pandas/tests/frame/methods/test_set_axis.py b/pandas/tests/frame/methods/test_set_axis.py index 8e597e1e9fa69..7efd4434f8412 100644 --- a/pandas/tests/frame/methods/test_set_axis.py +++ b/pandas/tests/frame/methods/test_set_axis.py @@ -16,14 +16,9 @@ def obj(self): def test_set_axis(self, obj): # GH14636; this tests setting index for both Series and DataFrame new_index = list("abcd")[: len(obj)] - expected = obj.copy() expected.index = new_index - - # inplace=False - msg = "set_axis 'inplace' keyword is deprecated" - with tm.assert_produces_warning(FutureWarning, match=msg): - result = obj.set_axis(new_index, axis=0, inplace=False) + result = obj.set_axis(new_index, axis=0) tm.assert_equal(expected, result) def test_set_axis_copy(self, obj): @@ -34,12 +29,6 @@ def test_set_axis_copy(self, obj): expected = obj.copy() expected.index = new_index - with pytest.raises( - ValueError, match="Cannot specify both inplace=True and copy=True" - ): - with tm.assert_produces_warning(FutureWarning): - obj.set_axis(new_index, axis=0, inplace=True, copy=True) - result = obj.set_axis(new_index, axis=0, copy=True) tm.assert_equal(expected, result) assert result is not obj @@ -77,40 +66,17 @@ def test_set_axis_copy(self, obj): for i in range(obj.shape[1]) ) - # Do this last since it alters obj inplace - with tm.assert_produces_warning(FutureWarning): - res = obj.set_axis(new_index, inplace=True, copy=False) - assert res is None - tm.assert_equal(expected, obj) + res = obj.set_axis(new_index, copy=False) + tm.assert_equal(expected, res) # check we did NOT make a copy - if obj.ndim == 1: - assert tm.shares_memory(obj, orig) + if res.ndim == 1: + assert tm.shares_memory(res, orig) else: assert all( - tm.shares_memory(obj.iloc[:, i], orig.iloc[:, i]) - for i in range(obj.shape[1]) + tm.shares_memory(res.iloc[:, i], orig.iloc[:, i]) + for i in range(res.shape[1]) ) - @pytest.mark.parametrize("axis", [0, "index", 1, "columns"]) - def test_set_axis_inplace_axis(self, axis, obj): - # GH#14636 - if obj.ndim == 1 and axis in [1, "columns"]: - # Series only has [0, "index"] - return - - new_index = list("abcd")[: len(obj)] - - expected = obj.copy() - if axis in [0, "index"]: - expected.index = new_index - else: - expected.columns = new_index - - result = obj.copy() - with tm.assert_produces_warning(FutureWarning): - result.set_axis(new_index, axis=axis, inplace=True) - tm.assert_equal(result, expected) - def test_set_axis_unnamed_kwarg_warns(self, obj): # omitting the "axis" parameter new_index = list("abcd")[: len(obj)] @@ -118,10 +84,7 @@ def test_set_axis_unnamed_kwarg_warns(self, obj): expected = obj.copy() expected.index = new_index - with tm.assert_produces_warning( - FutureWarning, match="set_axis 'inplace' keyword" - ): - result = obj.set_axis(new_index, inplace=False) + result = obj.set_axis(new_index) tm.assert_equal(result, expected) @pytest.mark.parametrize("axis", [3, "foo"]) diff --git a/pandas/tests/generic/test_duplicate_labels.py b/pandas/tests/generic/test_duplicate_labels.py index c9036958cbd74..d6d5c29e6d888 100644 --- a/pandas/tests/generic/test_duplicate_labels.py +++ b/pandas/tests/generic/test_duplicate_labels.py @@ -414,7 +414,6 @@ def test_dataframe_insert_raises(): "method, frame_only", [ (operator.methodcaller("set_index", "A", inplace=True), True), - (operator.methodcaller("set_axis", ["A", "B"], inplace=True), False), (operator.methodcaller("reset_index", inplace=True), True), (operator.methodcaller("rename", lambda x: x, inplace=True), False), ], @@ -427,19 +426,11 @@ def test_inplace_raises(method, frame_only): s.flags.allows_duplicate_labels = False msg = "Cannot specify" - warn_msg = "Series.set_axis 'inplace' keyword" - if "set_axis" in str(method): - warn = FutureWarning - else: - warn = None - with pytest.raises(ValueError, match=msg): - with tm.assert_produces_warning(warn, match=warn_msg): - method(df) + method(df) if not frame_only: with pytest.raises(ValueError, match=msg): - with tm.assert_produces_warning(warn, match=warn_msg): - method(s) + method(s) def test_pickle(): From 5884e6ba7085e35f4038e604a3e077e5c82f0606 Mon Sep 17 00:00:00 2001 From: Luke Manley Date: Tue, 1 Nov 2022 21:28:27 -0400 Subject: [PATCH 2/2] default copy to True --- pandas/core/frame.py | 4 ++-- pandas/core/generic.py | 7 ++----- pandas/core/series.py | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index b45e3ba93181b..c8c718b938e5e 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -5101,8 +5101,8 @@ def set_axis( labels, *, axis: Axis = 0, - copy: bool | lib.NoDefault = lib.no_default, - ): + copy: bool = True, + ) -> DataFrame: return super().set_axis(labels, axis=axis, copy=copy) @Substitution(**_shared_doc_kwargs) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 603d5376e824f..40714fe9a726b 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -703,8 +703,8 @@ def set_axis( labels, *, axis: Axis = 0, - copy: bool_t | lib.NoDefault = lib.no_default, - ) -> NDFrameT | None: + copy: bool_t = True, + ) -> NDFrameT: """ Assign desired index to given axis. @@ -734,9 +734,6 @@ def set_axis( -------- %(klass)s.rename_axis : Alter the name of the index%(see_also_sub)s. """ - if copy is lib.no_default: - copy = True - return self._set_axis_nocheck(labels, axis, inplace=False, copy=copy) @final diff --git a/pandas/core/series.py b/pandas/core/series.py index 4037d16d36920..9be9d70a593d3 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -4968,13 +4968,13 @@ def rename( see_also_sub="", ) @Appender(NDFrame.set_axis.__doc__) - def set_axis( # type: ignore[override] + def set_axis( self, labels, *, axis: Axis = 0, - copy: bool | lib.NoDefault = lib.no_default, - ) -> Series | None: + copy: bool = True, + ) -> Series: return super().set_axis(labels, axis=axis, copy=copy) # error: Cannot determine type of 'reindex'