diff --git a/doc/redirects.csv b/doc/redirects.csv index 8c46cb520cc95..05fe17868b261 100644 --- a/doc/redirects.csv +++ b/doc/redirects.csv @@ -481,7 +481,6 @@ generated/pandas.DataFrame.style,../reference/api/pandas.DataFrame.style generated/pandas.DataFrame.sub,../reference/api/pandas.DataFrame.sub generated/pandas.DataFrame.subtract,../reference/api/pandas.DataFrame.subtract generated/pandas.DataFrame.sum,../reference/api/pandas.DataFrame.sum -generated/pandas.DataFrame.swapaxes,../reference/api/pandas.DataFrame.swapaxes generated/pandas.DataFrame.swaplevel,../reference/api/pandas.DataFrame.swaplevel generated/pandas.DataFrame.tail,../reference/api/pandas.DataFrame.tail generated/pandas.DataFrame.take,../reference/api/pandas.DataFrame.take @@ -1206,7 +1205,6 @@ generated/pandas.Series.str.zfill,../reference/api/pandas.Series.str.zfill generated/pandas.Series.sub,../reference/api/pandas.Series.sub generated/pandas.Series.subtract,../reference/api/pandas.Series.subtract generated/pandas.Series.sum,../reference/api/pandas.Series.sum -generated/pandas.Series.swapaxes,../reference/api/pandas.Series.swapaxes generated/pandas.Series.swaplevel,../reference/api/pandas.Series.swaplevel generated/pandas.Series.tail,../reference/api/pandas.Series.tail generated/pandas.Series.take,../reference/api/pandas.Series.take diff --git a/doc/source/reference/frame.rst b/doc/source/reference/frame.rst index d09ca416e32a6..9cd9d6a157aee 100644 --- a/doc/source/reference/frame.rst +++ b/doc/source/reference/frame.rst @@ -235,7 +235,6 @@ Reshaping, sorting, transposing DataFrame.swaplevel DataFrame.stack DataFrame.unstack - DataFrame.swapaxes DataFrame.melt DataFrame.explode DataFrame.squeeze diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index aa378faac2a00..bb412b5b97c42 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -109,6 +109,7 @@ Removal of prior version deprecations/changes - Removed :meth:`DataFrame.applymap`, :meth:`Styler.applymap` and :meth:`Styler.applymap_index` (:issue:`52364`) - Removed ``DataFrame.bool`` and ``Series.bool`` (:issue:`51756`) - Removed ``DataFrame.first`` and ``DataFrame.last`` (:issue:`53710`) +- Removed ``DataFrame.swapaxes`` and ``Series.swapaxes`` (:issue:`51946`) - Removed ``DataFrameGroupBy.grouper`` and ``SeriesGroupBy.grouper`` (:issue:`56521`) - Removed ``DataFrameGroupby.fillna`` and ``SeriesGroupBy.fillna``` (:issue:`55719`) - Removed ``Index.format``, use :meth:`Index.astype` with ``str`` or :meth:`Index.map` with a ``formatter`` function instead (:issue:`55439`) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 8e0767d9b3699..afdbf157a04fa 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -161,7 +161,6 @@ ensure_index, ) from pandas.core.internals import BlockManager -from pandas.core.internals.construction import ndarray_to_mgr from pandas.core.methods.describe import describe_ndframe from pandas.core.missing import ( clean_fill_method, @@ -755,66 +754,6 @@ def _set_axis(self, axis: AxisInt, labels: AnyArrayLike | list) -> None: labels = ensure_index(labels) self._mgr.set_axis(axis, labels) - @final - def swapaxes(self, axis1: Axis, axis2: Axis, copy: bool | None = None) -> Self: - """ - Interchange axes and swap values axes appropriately. - - .. deprecated:: 2.1.0 - ``swapaxes`` is deprecated and will be removed. - Please use ``transpose`` instead. - - Returns - ------- - same as input - - Examples - -------- - Please see examples for :meth:`DataFrame.transpose`. - """ - 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) - - if i == j: - return self.copy(deep=False) - - mapping = {i: j, j: i} - - new_axes = [self._get_axis(mapping.get(k, k)) for k in range(self._AXIS_LEN)] - new_values = self._values.swapaxes(i, j) # type: ignore[union-attr] - if self._mgr.is_single_block and isinstance(self._mgr, BlockManager): - # This should only get hit in case of having a single block, otherwise a - # copy is made, we don't have to set up references. - new_mgr = ndarray_to_mgr( - new_values, - new_axes[0], - new_axes[1], - dtype=None, - copy=False, - ) - assert isinstance(new_mgr, BlockManager) - assert isinstance(self._mgr, BlockManager) - new_mgr.blocks[0].refs = self._mgr.blocks[0].refs - new_mgr.blocks[0].refs.add_reference(new_mgr.blocks[0]) - out = self._constructor_from_mgr(new_mgr, axes=new_mgr.axes) - return out.__finalize__(self, method="swapaxes") - - return self._constructor( - new_values, - *new_axes, - # The no-copy case for CoW is handled above - copy=False, - ).__finalize__(self, method="swapaxes") - @final @doc(klass=_shared_doc_kwargs["klass"]) def droplevel(self, level: IndexLabel, axis: Axis = 0) -> Self: diff --git a/pandas/tests/copy_view/test_methods.py b/pandas/tests/copy_view/test_methods.py index 356b31a82f5ff..73919997fa7fd 100644 --- a/pandas/tests/copy_view/test_methods.py +++ b/pandas/tests/copy_view/test_methods.py @@ -86,7 +86,6 @@ def test_copy_shallow(using_copy_on_write): lambda df, copy: df.rename_axis(columns="test", copy=copy), lambda df, copy: df.astype({"b": "int64"}, copy=copy), # lambda df, copy: df.swaplevel(0, 0, copy=copy), - lambda df, copy: df.swapaxes(0, 0, copy=copy), lambda df, copy: df.truncate(0, 5, copy=copy), lambda df, copy: df.infer_objects(copy=copy), lambda df, copy: df.to_timestamp(copy=copy), @@ -105,7 +104,6 @@ def test_copy_shallow(using_copy_on_write): "rename_axis1", "astype", # "swaplevel", # only series - "swapaxes", "truncate", "infer_objects", "to_timestamp", @@ -127,13 +125,7 @@ def test_methods_copy_keyword(request, method, copy, using_copy_on_write): 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) - - 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) + df2 = method(df, copy=copy) share_memory = using_copy_on_write or copy is False @@ -161,7 +153,6 @@ def test_methods_copy_keyword(request, method, copy, using_copy_on_write): lambda ser, copy: ser.rename_axis(index="test", copy=copy), lambda ser, copy: ser.astype("int64", copy=copy), lambda ser, copy: ser.swaplevel(0, 1, copy=copy), - lambda ser, copy: ser.swapaxes(0, 0, copy=copy), lambda ser, copy: ser.truncate(0, 5, copy=copy), lambda ser, copy: ser.infer_objects(copy=copy), lambda ser, copy: ser.to_timestamp(copy=copy), @@ -180,7 +171,6 @@ def test_methods_copy_keyword(request, method, copy, using_copy_on_write): "rename_axis0", "astype", "swaplevel", - "swapaxes", "truncate", "infer_objects", "to_timestamp", @@ -204,13 +194,7 @@ 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) - - 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) + ser2 = method(ser, copy=copy) share_memory = using_copy_on_write or copy is False @@ -688,55 +672,6 @@ def test_to_frame(using_copy_on_write): tm.assert_frame_equal(df, expected) -@pytest.mark.parametrize("ax", ["index", "columns"]) -def test_swapaxes_noop(using_copy_on_write, ax): - df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) - df_orig = df.copy() - 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")) - else: - assert not np.shares_memory(get_array(df2, "a"), get_array(df, "a")) - - # mutating df2 triggers a copy-on-write for that column/block - df2.iloc[0, 0] = 0 - if using_copy_on_write: - assert not np.shares_memory(get_array(df2, "a"), get_array(df, "a")) - tm.assert_frame_equal(df, df_orig) - - -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() - 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")) - else: - assert not np.shares_memory(get_array(df2, "x"), get_array(df, "a")) - - # mutating df2 triggers a copy-on-write for that column/block - df2.iloc[0, 0] = 0 - if using_copy_on_write: - assert not np.shares_memory(get_array(df2, "x"), get_array(df, "a")) - tm.assert_frame_equal(df, df_orig) - - -def test_swapaxes_read_only_array(): - df = DataFrame({"a": [1, 2], "b": 3}) - 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) - - @pytest.mark.parametrize( "method, idx", [ diff --git a/pandas/tests/frame/methods/test_swapaxes.py b/pandas/tests/frame/methods/test_swapaxes.py deleted file mode 100644 index 53a4691d48b1c..0000000000000 --- a/pandas/tests/frame/methods/test_swapaxes.py +++ /dev/null @@ -1,37 +0,0 @@ -import numpy as np -import pytest - -from pandas import DataFrame -import pandas._testing as tm - - -class TestSwapAxes: - def test_swapaxes(self): - df = DataFrame(np.random.default_rng(2).standard_normal((10, 5))) - 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.default_rng(2).standard_normal((10, 5))) - 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.default_rng(2).standard_normal((10, 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]}) - 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_generic.py b/pandas/tests/generic/test_generic.py index 277ea4e72c6a2..cdb34a00b952c 100644 --- a/pandas/tests/generic/test_generic.py +++ b/pandas/tests/generic/test_generic.py @@ -232,11 +232,8 @@ 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) - 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 + 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):