From 50c453b30e2cd094010380d63816775ae7db7a2a Mon Sep 17 00:00:00 2001 From: Patrick Hoefler <61934744+phofl@users.noreply.github.com> Date: Sun, 3 Sep 2023 16:57:05 +0200 Subject: [PATCH 1/3] BUG: pct_change showing unnecessary FutureWarning --- doc/source/whatsnew/v2.1.1.rst | 1 + pandas/core/generic.py | 4 +++- pandas/tests/series/methods/test_pct_change.py | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.1.1.rst b/doc/source/whatsnew/v2.1.1.rst index a6848dad6e3cd..3534a275122c0 100644 --- a/doc/source/whatsnew/v2.1.1.rst +++ b/doc/source/whatsnew/v2.1.1.rst @@ -29,6 +29,7 @@ Fixed regressions Bug fixes ~~~~~~~~~ - Fixed bug in :meth:`DataFrame.stack` with ``future_stack=True`` and columns a non-:class:`MultiIndex` consisting of tuples (:issue:`54948`) +- Fixed bug in :meth:`Series.pct_change` and :meth:`DataFrame.pct_change` showing unnecessary ``FutureWarning`` (:issue:`54981`) .. --------------------------------------------------------------------------- .. _whatsnew_211.other: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index b9407ebe6624a..83f3ac3ed042e 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -11709,7 +11709,9 @@ def pct_change( stacklevel=find_stack_level(), ) if fill_method is lib.no_default: - if self.isna().values.any(): + mask = self.isna().values + mask = mask[np.argmax(~mask) :] + if mask.any(): warnings.warn( "The default fill_method='pad' in " f"{type(self).__name__}.pct_change is deprecated and will be " diff --git a/pandas/tests/series/methods/test_pct_change.py b/pandas/tests/series/methods/test_pct_change.py index 4dabf7b87e2cd..6740b8756853e 100644 --- a/pandas/tests/series/methods/test_pct_change.py +++ b/pandas/tests/series/methods/test_pct_change.py @@ -107,3 +107,11 @@ def test_pct_change_with_duplicated_indices(fill_method): expected = Series([np.nan, np.nan, 1.0, 0.5, 2.0, 1.0], index=["a", "b"] * 3) tm.assert_series_equal(result, expected) + + +def test_pct_change_no_warning_na_beginning(): + # GH#54981 + ser = Series([None, None, 1, 2, 3]) + result = ser.pct_change() + expected = Series([np.nan, np.nan, np.nan, 1, 0.5]) + tm.assert_series_equal(result, expected) From b976afdcae4acedc92dcbd9f566859d3f2ec9aa4 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Tue, 5 Sep 2023 14:30:33 +0200 Subject: [PATCH 2/3] Fix df case --- pandas/core/generic.py | 25 +++++++++++-------- pandas/tests/frame/methods/test_pct_change.py | 18 +++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 83f3ac3ed042e..0bf925ceee2d1 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -11709,17 +11709,20 @@ def pct_change( stacklevel=find_stack_level(), ) if fill_method is lib.no_default: - mask = self.isna().values - mask = mask[np.argmax(~mask) :] - if mask.any(): - warnings.warn( - "The default fill_method='pad' in " - f"{type(self).__name__}.pct_change is deprecated and will be " - "removed in a future version. Call ffill before calling " - "pct_change to retain current behavior and silence this warning.", - FutureWarning, - stacklevel=find_stack_level(), - ) + for _, col in self.items(): + mask = col.isna().values + mask = mask[np.argmax(~mask) :] + if mask.any(): + warnings.warn( + "The default fill_method='pad' in " + f"{type(self).__name__}.pct_change is deprecated and will be " + "removed in a future version. Call ffill before calling " + "pct_change to retain current behavior and silence this " + "warning.", + FutureWarning, + stacklevel=find_stack_level(), + ) + break fill_method = "pad" if limit is lib.no_default: limit = None diff --git a/pandas/tests/frame/methods/test_pct_change.py b/pandas/tests/frame/methods/test_pct_change.py index d0153da038a75..ede212ae18ae9 100644 --- a/pandas/tests/frame/methods/test_pct_change.py +++ b/pandas/tests/frame/methods/test_pct_change.py @@ -160,3 +160,21 @@ def test_pct_change_with_duplicated_indices(fill_method): index=["a", "b"] * 3, ) tm.assert_frame_equal(result, expected) + + +def test_pct_change_none_beginning_no_warning(): + # GH#54481 + df = DataFrame( + [ + [1, None], + [2, 1], + [3, 2], + [4, 3], + [5, 4], + ] + ) + result = df.pct_change() + expected = DataFrame( + {0: [np.nan, 1, 0.5, 1 / 3, 0.25], 1: [np.nan, np.nan, 1, 0.5, 1 / 3]} + ) + tm.assert_frame_equal(result, expected) From e353fc98ea0cc8323d6ce9775dfd7325cffa4e56 Mon Sep 17 00:00:00 2001 From: Patrick Hoefler Date: Wed, 6 Sep 2023 22:12:40 +0200 Subject: [PATCH 3/3] Fix --- pandas/core/generic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 52a6f243609a5..fb3549be96ec1 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -11793,7 +11793,8 @@ def pct_change( stacklevel=find_stack_level(), ) if fill_method is lib.no_default: - for _, col in self.items(): + cols = self.items() if self.ndim == 2 else [(None, self)] + for _, col in cols: mask = col.isna().values mask = mask[np.argmax(~mask) :] if mask.any():