From b2f2774d329ff3c1dfadf3e497e1e2a5f447fd06 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Sun, 19 Nov 2023 00:54:25 +0100 Subject: [PATCH 01/11] DEP: Deprecate ravel --- doc/source/whatsnew/v2.2.0.rst | 1 + pandas/core/series.py | 5 +++++ pandas/tests/series/test_api.py | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index a33322aebab34..a2c6db1f69066 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -266,6 +266,7 @@ Other Deprecations - Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`) - Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`) - Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`) +- Deprecated :meth:`Series.ravel`, use ``np.ravel`` instead (:issue:`52511`) - Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`) - Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_clipboard`. (:issue:`54229`) - Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_csv` except ``path_or_buf``. (:issue:`54229`) diff --git a/pandas/core/series.py b/pandas/core/series.py index 1bbd10429ea22..bf469d91a59c4 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -861,6 +861,11 @@ def ravel(self, order: str = "C") -> ArrayLike: >>> s.ravel() array([1, 2, 3]) """ + warnings.warn( + "Series.ravel is deprecated. Use numpy.ravel directly.", + FutureWarning, + stacklevel=find_stack_level(), + ) arr = self._values.ravel(order=order) if isinstance(arr, np.ndarray) and using_copy_on_write(): arr.flags.writeable = False diff --git a/pandas/tests/series/test_api.py b/pandas/tests/series/test_api.py index a39b3ff7e6f2b..97739e589d157 100644 --- a/pandas/tests/series/test_api.py +++ b/pandas/tests/series/test_api.py @@ -140,7 +140,9 @@ def test_ndarray_compat_like_func(self): def test_ndarray_compat_ravel(self): # ravel s = Series(np.random.default_rng(2).standard_normal(10)) - tm.assert_almost_equal(s.ravel(order="F"), s.values.ravel(order="F")) + with tm.assert_produces_warning(FutureWarning, match="ravel is deprecated"): + result = s.ravel(order="F") + tm.assert_almost_equal(result, s.values.ravel(order="F")) def test_empty_method(self): s_empty = Series(dtype=object) From dd9cfe636a90007c120c5b630b53850482ea893b Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Sun, 19 Nov 2023 15:00:51 +0100 Subject: [PATCH 02/11] Fix ravel deprecations --- pandas/_testing/asserters.py | 2 ++ pandas/core/reshape/pivot.py | 2 +- pandas/tests/copy_view/test_array.py | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/_testing/asserters.py b/pandas/_testing/asserters.py index 0d8fb7bfce33a..55cf734c32eae 100644 --- a/pandas/_testing/asserters.py +++ b/pandas/_testing/asserters.py @@ -426,6 +426,8 @@ def assert_is_valid_plot_return_object(objs) -> None: from matplotlib.axes import Axes if isinstance(objs, (Series, np.ndarray)): + if isinstance(objs, Series): + objs = objs._values for el in objs.ravel(): msg = ( "one of 'objs' is not a matplotlib Axes instance, " diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 79354fdd12a2d..94fcb3c2831f7 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -316,7 +316,7 @@ def _add_margins( cols = result.select_dtypes([dtype]).columns margin_dummy[cols] = margin_dummy[cols].apply( - maybe_downcast_to_dtype, args=(dtype,) + lambda x: maybe_downcast_to_dtype(x._values, dtype) ) result = result._append(margin_dummy) result.index.names = row_names diff --git a/pandas/tests/copy_view/test_array.py b/pandas/tests/copy_view/test_array.py index 62a6a3374e612..e5d0aafb80b35 100644 --- a/pandas/tests/copy_view/test_array.py +++ b/pandas/tests/copy_view/test_array.py @@ -116,7 +116,8 @@ def test_series_to_numpy(using_copy_on_write): @pytest.mark.parametrize("order", ["F", "C"]) def test_ravel_read_only(using_copy_on_write, order): ser = Series([1, 2, 3]) - arr = ser.ravel(order=order) + with tm.assert_produces_warning(FutureWarning, match="is deprecated"): + arr = ser.ravel(order=order) if using_copy_on_write: assert arr.flags.writeable is False assert np.shares_memory(get_array(ser), arr) From 054ca87d24b1766d33dd448451601a9febd57cf1 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:51:41 +0100 Subject: [PATCH 03/11] Update pivot.py --- pandas/core/reshape/pivot.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 94fcb3c2831f7..a3a6febbd4b40 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -309,6 +309,10 @@ def _add_margins( row_names = result.index.names # check the result column and leave floats + + def cast_types(x, dtype): + return maybe_downcast_to_dtype(x._values, dtype) + for dtype in set(result.dtypes): if isinstance(dtype, ExtensionDtype): # Can hold NA already @@ -316,7 +320,7 @@ def _add_margins( cols = result.select_dtypes([dtype]).columns margin_dummy[cols] = margin_dummy[cols].apply( - lambda x: maybe_downcast_to_dtype(x._values, dtype) + cast_types, arg=(dtype, ) ) result = result._append(margin_dummy) result.index.names = row_names From 5a153892425a7dec5acb925d86ceb741c1bf0338 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:54:36 +0100 Subject: [PATCH 04/11] Fix doctest --- pandas/core/series.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index bf469d91a59c4..522e2e5eb09b6 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -858,14 +858,9 @@ def ravel(self, order: str = "C") -> ArrayLike: Examples -------- >>> s = pd.Series([1, 2, 3]) - >>> s.ravel() + >>> s.ravel() # doctest: +SKIP array([1, 2, 3]) """ - warnings.warn( - "Series.ravel is deprecated. Use numpy.ravel directly.", - FutureWarning, - stacklevel=find_stack_level(), - ) arr = self._values.ravel(order=order) if isinstance(arr, np.ndarray) and using_copy_on_write(): arr.flags.writeable = False @@ -943,6 +938,11 @@ def view(self, dtype: Dtype | None = None) -> Series: 4 2 dtype: int8 """ + warnings.warn( + "Series.view is deprecated and will be removed in a future version.", + FutureWarning, + stacklevel=find_stack_level(), + ) # self.array instead of self._values so we piggyback on NumpyExtensionArray # implementation res_values = self.array.view(dtype) From 28fb76c43074492123e058302d84e8c76d2550fc Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Mon, 20 Nov 2023 00:10:51 +0100 Subject: [PATCH 05/11] Fix view --- pandas/core/series.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 522e2e5eb09b6..699ab37e90c2c 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -861,6 +861,11 @@ def ravel(self, order: str = "C") -> ArrayLike: >>> s.ravel() # doctest: +SKIP array([1, 2, 3]) """ + warnings.warn( + "Series.ravel is deprecated. Use numpy.ravel directly.", + FutureWarning, + stacklevel=find_stack_level(), + ) arr = self._values.ravel(order=order) if isinstance(arr, np.ndarray) and using_copy_on_write(): arr.flags.writeable = False @@ -938,11 +943,6 @@ def view(self, dtype: Dtype | None = None) -> Series: 4 2 dtype: int8 """ - warnings.warn( - "Series.view is deprecated and will be removed in a future version.", - FutureWarning, - stacklevel=find_stack_level(), - ) # self.array instead of self._values so we piggyback on NumpyExtensionArray # implementation res_values = self.array.view(dtype) From 636e3c44c71c22316ca4dc208b320943e0b6b121 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Mon, 20 Nov 2023 01:49:55 +0100 Subject: [PATCH 06/11] Fix --- pandas/core/reshape/pivot.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index a3a6febbd4b40..bb387079403d2 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -310,7 +310,7 @@ def _add_margins( row_names = result.index.names # check the result column and leave floats - def cast_types(x, dtype): + def _cast_types(x, dtype): return maybe_downcast_to_dtype(x._values, dtype) for dtype in set(result.dtypes): @@ -319,9 +319,7 @@ def cast_types(x, dtype): continue cols = result.select_dtypes([dtype]).columns - margin_dummy[cols] = margin_dummy[cols].apply( - cast_types, arg=(dtype, ) - ) + margin_dummy[cols] = margin_dummy[cols].apply(_cast_types, args=(dtype,)) result = result._append(margin_dummy) result.index.names = row_names From d48e5ca16998d2c9dbda400c65710da9903d550b Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:53:48 +0100 Subject: [PATCH 07/11] Update --- pandas/core/dtypes/cast.py | 2 ++ pandas/core/reshape/pivot.py | 7 +++---- pandas/core/series.py | 7 +++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 0ad652bd5aa64..79747513eabe9 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -261,6 +261,8 @@ def maybe_downcast_to_dtype(result: ArrayLike, dtype: str | np.dtype) -> ArrayLi try to cast to the specified dtype (e.g. convert back to bool/int or could be an astype of float64->float32 """ + if isinstance(result, ABCSeries): + result = result._values do_round = False if isinstance(dtype, str): diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index bb387079403d2..974578445f503 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -310,16 +310,15 @@ def _add_margins( row_names = result.index.names # check the result column and leave floats - def _cast_types(x, dtype): - return maybe_downcast_to_dtype(x._values, dtype) - for dtype in set(result.dtypes): if isinstance(dtype, ExtensionDtype): # Can hold NA already continue cols = result.select_dtypes([dtype]).columns - margin_dummy[cols] = margin_dummy[cols].apply(_cast_types, args=(dtype,)) + margin_dummy[cols] = margin_dummy[cols].apply( + maybe_downcast_to_dtype, args=(dtype,) + ) result = result._append(margin_dummy) result.index.names = row_names diff --git a/pandas/core/series.py b/pandas/core/series.py index 699ab37e90c2c..1d0146bc4e875 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -846,6 +846,8 @@ def ravel(self, order: str = "C") -> ArrayLike: """ Return the flattened underlying data as an ndarray or ExtensionArray. + .. deprecated:: 2.2.0 + Returns ------- numpy.ndarray or ExtensionArray @@ -862,9 +864,10 @@ def ravel(self, order: str = "C") -> ArrayLike: array([1, 2, 3]) """ warnings.warn( - "Series.ravel is deprecated. Use numpy.ravel directly.", + "Series.ravel is deprecated. The underlying array is already 1D, so " + "ravel is not necessary.", FutureWarning, - stacklevel=find_stack_level(), + stacklevel=2, ) arr = self._values.ravel(order=order) if isinstance(arr, np.ndarray) and using_copy_on_write(): From 146e1aacbda8c59472d95560a605c2a775bd913b Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:54:21 +0100 Subject: [PATCH 08/11] Update whatsnew --- doc/source/whatsnew/v2.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 7cefbda6cb345..8437d97c69f48 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -266,7 +266,7 @@ Other Deprecations - Deprecated :func:`read_gbq` and :meth:`DataFrame.to_gbq`. Use ``pandas_gbq.read_gbq`` and ``pandas_gbq.to_gbq`` instead https://pandas-gbq.readthedocs.io/en/latest/api.html (:issue:`55525`) - Deprecated :meth:`.DataFrameGroupBy.fillna` and :meth:`.SeriesGroupBy.fillna`; use :meth:`.DataFrameGroupBy.ffill`, :meth:`.DataFrameGroupBy.bfill` for forward and backward filling or :meth:`.DataFrame.fillna` to fill with a single value (or the Series equivalents) (:issue:`55718`) - Deprecated :meth:`Index.format`, use ``index.astype(str)`` or ``index.map(formatter)`` instead (:issue:`55413`) -- Deprecated :meth:`Series.ravel`, use ``np.ravel`` instead (:issue:`52511`) +- Deprecated :meth:`Series.ravel`, the underlying array is already 1D, so ravel is not necessary (:issue:`52511`) - Deprecated ``year``, ``month``, ``quarter``, ``day``, ``hour``, ``minute``, and ``second`` keywords in the :class:`PeriodIndex` constructor, use :meth:`PeriodIndex.from_fields` instead (:issue:`55960`) - Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_clipboard`. (:issue:`54229`) - Deprecated allowing non-keyword arguments in :meth:`DataFrame.to_csv` except ``path_or_buf``. (:issue:`54229`) From 571bc1a158c72b590114588d5f35b6bed1e24577 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Tue, 21 Nov 2023 21:23:46 +0100 Subject: [PATCH 09/11] FIx --- pandas/tests/dtypes/cast/test_downcast.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/dtypes/cast/test_downcast.py b/pandas/tests/dtypes/cast/test_downcast.py index c01eac746455c..9430ba2c478ae 100644 --- a/pandas/tests/dtypes/cast/test_downcast.py +++ b/pandas/tests/dtypes/cast/test_downcast.py @@ -56,8 +56,8 @@ def test_downcast_booleans(): ser = Series([True, True, False]) result = maybe_downcast_to_dtype(ser, np.dtype(np.float64)) - expected = ser - tm.assert_series_equal(result, expected) + expected = ser.values + tm.assert_numpy_array_equal(result, expected) def test_downcast_conversion_no_nan(any_real_numpy_dtype): From d54a80c3a514122dfde5cce82ec96aa69c940a4e Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Tue, 21 Nov 2023 23:03:15 +0100 Subject: [PATCH 10/11] Add note --- pandas/core/series.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 1d0146bc4e875..398cf349d63a4 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -847,6 +847,9 @@ def ravel(self, order: str = "C") -> ArrayLike: Return the flattened underlying data as an ndarray or ExtensionArray. .. deprecated:: 2.2.0 + Series.ravel is deprecated. The underlying array is already 1D, so + ravel is not necessary. Use `to_numpy()` for conversion to a numpy + array instead. Returns ------- @@ -865,7 +868,8 @@ def ravel(self, order: str = "C") -> ArrayLike: """ warnings.warn( "Series.ravel is deprecated. The underlying array is already 1D, so " - "ravel is not necessary.", + "ravel is not necessary. Use `to_numpy()` for conversion to a numpy " + "array instead.", FutureWarning, stacklevel=2, ) From 4afe81c39787de5908eed6473af71768a3a5b88d Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Mon, 27 Nov 2023 12:23:28 +0100 Subject: [PATCH 11/11] Update pandas/core/series.py --- pandas/core/series.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 138f7d4319f7e..82842e84acb60 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -849,7 +849,7 @@ def ravel(self, order: str = "C") -> ArrayLike: .. deprecated:: 2.2.0 Series.ravel is deprecated. The underlying array is already 1D, so - ravel is not necessary. Use `to_numpy()` for conversion to a numpy + ravel is not necessary. Use :meth:`to_numpy` for conversion to a numpy array instead. Returns