diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index 1f5c3c88c5ff5..71fda39a05e55 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -114,6 +114,7 @@ Deprecations - Deprecated 'method', 'limit', and 'fill_axis' keywords in :meth:`DataFrame.align` and :meth:`Series.align`, explicitly call ``fillna`` on the alignment results instead (:issue:`51856`) - Deprecated 'broadcast_axis' keyword in :meth:`Series.align` and :meth:`DataFrame.align`, upcast before calling ``align`` with ``left = DataFrame({col: left for col in right.columns}, index=right.index)`` (:issue:`51856`) - Deprecated the 'axis' keyword in :meth:`.GroupBy.idxmax`, :meth:`.GroupBy.idxmin`, :meth:`.GroupBy.fillna`, :meth:`.GroupBy.take`, :meth:`.GroupBy.skew`, :meth:`.GroupBy.rank`, :meth:`.GroupBy.cumprod`, :meth:`.GroupBy.cumsum`, :meth:`.GroupBy.cummax`, :meth:`.GroupBy.cummin`, :meth:`.GroupBy.pct_change`, :meth:`GroupBy.diff`, :meth:`.GroupBy.shift`, and :meth:`DataFrameGroupBy.corrwith`; for ``axis=1`` operate on the underlying :class:`DataFrame` instead (:issue:`50405`, :issue:`51046`) +- Deprecated :meth:`DataFrame.swapaxes` and :meth:`Series.swapaxes`, use :meth:`DataFrame.transpose` or :meth:`Series.transpose` instead (:issue:`51946`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 2b650d99c7e6c..80ac49d460d3d 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -741,6 +741,15 @@ def swapaxes(self, axis1: Axis, axis2: Axis, copy: bool_t | None = None) -> Self ------- same as input """ + warnings.warn( + # GH#51946 + f"'{type(self).__name__}.swapaxes' is deprecated and " + "will be removed in a future version. " + f"Please use '{type(self).__name__}.transpose' instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) + i = self._get_axis_number(axis1) j = self._get_axis_number(axis2) diff --git a/pandas/tests/copy_view/test_methods.py b/pandas/tests/copy_view/test_methods.py index 1d8f1dea7d478..7b8bc35f016b1 100644 --- a/pandas/tests/copy_view/test_methods.py +++ b/pandas/tests/copy_view/test_methods.py @@ -115,7 +115,13 @@ def test_methods_copy_keyword( index = date_range("2012-01-01", freq="D", periods=3, tz="Europe/Brussels") df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6], "c": [0.1, 0.2, 0.3]}, index=index) - df2 = method(df, copy=copy) + + if "swapaxes" in request.node.callspec.id: + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + df2 = method(df, copy=copy) + else: + df2 = method(df, copy=copy) share_memory = using_copy_on_write or copy is False @@ -184,7 +190,13 @@ def test_methods_series_copy_keyword(request, method, copy, using_copy_on_write) index = MultiIndex.from_arrays([[1, 2, 3], [4, 5, 6]]) ser = Series([1, 2, 3], index=index) - ser2 = method(ser, copy=copy) + + if "swapaxes" in request.node.callspec.id: + msg = "'Series.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + ser2 = method(ser, copy=copy) + else: + ser2 = method(ser, copy=copy) share_memory = using_copy_on_write or copy is False @@ -625,7 +637,9 @@ def test_to_frame(using_copy_on_write): def test_swapaxes_noop(using_copy_on_write, ax): df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) df_orig = df.copy() - df2 = df.swapaxes(ax, ax) + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + df2 = df.swapaxes(ax, ax) if using_copy_on_write: assert np.shares_memory(get_array(df2, "a"), get_array(df, "a")) @@ -642,7 +656,9 @@ def test_swapaxes_noop(using_copy_on_write, ax): def test_swapaxes_single_block(using_copy_on_write): df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}, index=["x", "y", "z"]) df_orig = df.copy() - df2 = df.swapaxes("index", "columns") + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + df2 = df.swapaxes("index", "columns") if using_copy_on_write: assert np.shares_memory(get_array(df2, "x"), get_array(df, "a")) @@ -658,7 +674,9 @@ def test_swapaxes_single_block(using_copy_on_write): def test_swapaxes_read_only_array(): df = DataFrame({"a": [1, 2], "b": 3}) - df = df.swapaxes(axis1="index", axis2="columns") + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + df = df.swapaxes(axis1="index", axis2="columns") df.iloc[0, 0] = 100 expected = DataFrame({0: [100, 3], 1: [2, 3]}, index=["a", "b"]) tm.assert_frame_equal(df, expected) diff --git a/pandas/tests/frame/methods/test_swapaxes.py b/pandas/tests/frame/methods/test_swapaxes.py index 5da2c2292f137..f2667fc973cf4 100644 --- a/pandas/tests/frame/methods/test_swapaxes.py +++ b/pandas/tests/frame/methods/test_swapaxes.py @@ -8,22 +8,30 @@ class TestSwapAxes: def test_swapaxes(self): df = DataFrame(np.random.randn(10, 5)) - tm.assert_frame_equal(df.T, df.swapaxes(0, 1)) - tm.assert_frame_equal(df.T, df.swapaxes(1, 0)) + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + tm.assert_frame_equal(df.T, df.swapaxes(0, 1)) + tm.assert_frame_equal(df.T, df.swapaxes(1, 0)) def test_swapaxes_noop(self): df = DataFrame(np.random.randn(10, 5)) - tm.assert_frame_equal(df, df.swapaxes(0, 0)) + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + tm.assert_frame_equal(df, df.swapaxes(0, 0)) def test_swapaxes_invalid_axis(self): df = DataFrame(np.random.randn(10, 5)) - msg = "No axis named 2 for object type DataFrame" - with pytest.raises(ValueError, match=msg): - df.swapaxes(2, 5) + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + msg = "No axis named 2 for object type DataFrame" + with pytest.raises(ValueError, match=msg): + df.swapaxes(2, 5) def test_round_empty_not_input(self): # GH#51032 df = DataFrame({"a": [1, 2]}) - result = df.swapaxes("index", "index") + msg = "'DataFrame.swapaxes' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.swapaxes("index", "index") tm.assert_frame_equal(df, result) assert df is not result diff --git a/pandas/tests/generic/test_finalize.py b/pandas/tests/generic/test_finalize.py index d85de12566fb6..cdab112e7ad86 100644 --- a/pandas/tests/generic/test_finalize.py +++ b/pandas/tests/generic/test_finalize.py @@ -251,7 +251,6 @@ operator.methodcaller("isin", pd.DataFrame({"A": [1]})), ), ), - (pd.DataFrame, frame_data, operator.methodcaller("swapaxes", 0, 1)), (pd.DataFrame, frame_mi_data, operator.methodcaller("droplevel", "A")), (pd.DataFrame, frame_data, operator.methodcaller("pop", "A")), pytest.param( diff --git a/pandas/tests/generic/test_generic.py b/pandas/tests/generic/test_generic.py index 74d8277c975e4..d23d97f43de03 100644 --- a/pandas/tests/generic/test_generic.py +++ b/pandas/tests/generic/test_generic.py @@ -230,8 +230,11 @@ def test_size_compat(self, frame_or_series): def test_split_compat(self, frame_or_series): # xref GH8846 o = construct(frame_or_series, shape=10) - assert len(np.array_split(o, 5)) == 5 - assert len(np.array_split(o, 2)) == 2 + with tm.assert_produces_warning( + FutureWarning, match=".swapaxes' is deprecated", check_stacklevel=False + ): + assert len(np.array_split(o, 5)) == 5 + assert len(np.array_split(o, 2)) == 2 # See gh-12301 def test_stat_unexpected_keyword(self, frame_or_series):