Skip to content

Commit 54814c3

Browse files
authored
BUG fix deprecation of limit and fill_method in pct_change (pandas-dev#55527)
1 parent fe17818 commit 54814c3

File tree

7 files changed

+63
-48
lines changed

7 files changed

+63
-48
lines changed

doc/source/whatsnew/v2.1.2.rst

+8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ including other versions of pandas.
88

99
{{ header }}
1010

11+
.. ---------------------------------------------------------------------------
12+
.. _whatsnew_212.deprecations:
13+
14+
Deprecations
15+
~~~~~~~~~~~~
16+
17+
- Reverted deprecation of ``fill_method=None`` in :meth:`DataFrame.pct_change`, :meth:`Series.pct_change`, :meth:`DataFrameGroupBy.pct_change`, and :meth:`SeriesGroupBy.pct_change`; the values ``'backfill'``, ``'bfill'``, ``'pad'``, and ``'ffill'`` are still deprecated (:issue:`53491`)
18+
1119
.. ---------------------------------------------------------------------------
1220
.. _whatsnew_212.regressions:
1321

doc/source/whatsnew/v2.2.0.rst

-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,6 @@ Other Deprecations
288288
- Deprecated the option ``mode.data_manager`` and the ``ArrayManager``; only the ``BlockManager`` will be available in future versions (:issue:`55043`)
289289
- Deprecated the previous implementation of :class:`DataFrame.stack`; specify ``future_stack=True`` to adopt the future version (:issue:`53515`)
290290
- Deprecating downcasting the results of :meth:`DataFrame.fillna`, :meth:`Series.fillna`, :meth:`DataFrame.ffill`, :meth:`Series.ffill`, :meth:`DataFrame.bfill`, :meth:`Series.bfill` in object-dtype cases. To opt in to the future version, use ``pd.set_option("future.no_silent_downcasting", True)`` (:issue:`54261`)
291-
-
292291

293292
.. ---------------------------------------------------------------------------
294293
.. _whatsnew_220.performance:

pandas/core/generic.py

+23-21
Original file line numberDiff line numberDiff line change
@@ -11723,6 +11723,7 @@ def pct_change(
1172311723
How to handle NAs **before** computing percent changes.
1172411724
1172511725
.. deprecated:: 2.1
11726+
All options of `fill_method` are deprecated except `fill_method=None`.
1172611727
1172711728
limit : int, default None
1172811729
The number of consecutive NAs to fill before stopping.
@@ -11829,32 +11830,33 @@ def pct_change(
1182911830
APPL -0.252395 -0.011860 NaN
1183011831
"""
1183111832
# GH#53491
11832-
if fill_method is not lib.no_default or limit is not lib.no_default:
11833+
if fill_method not in (lib.no_default, None) or limit is not lib.no_default:
1183311834
warnings.warn(
11834-
"The 'fill_method' and 'limit' keywords in "
11835-
f"{type(self).__name__}.pct_change are deprecated and will be "
11836-
"removed in a future version. Call "
11837-
f"{'bfill' if fill_method in ('backfill', 'bfill') else 'ffill'} "
11838-
"before calling pct_change instead.",
11835+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
11836+
f"{type(self).__name__}.pct_change are deprecated and will be removed "
11837+
"in a future version. Either fill in any non-leading NA values prior "
11838+
"to calling pct_change or specify 'fill_method=None' to not fill NA "
11839+
"values.",
1183911840
FutureWarning,
1184011841
stacklevel=find_stack_level(),
1184111842
)
1184211843
if fill_method is lib.no_default:
11843-
cols = self.items() if self.ndim == 2 else [(None, self)]
11844-
for _, col in cols:
11845-
mask = col.isna().values
11846-
mask = mask[np.argmax(~mask) :]
11847-
if mask.any():
11848-
warnings.warn(
11849-
"The default fill_method='pad' in "
11850-
f"{type(self).__name__}.pct_change is deprecated and will be "
11851-
"removed in a future version. Call ffill before calling "
11852-
"pct_change to retain current behavior and silence this "
11853-
"warning.",
11854-
FutureWarning,
11855-
stacklevel=find_stack_level(),
11856-
)
11857-
break
11844+
if limit is lib.no_default:
11845+
cols = self.items() if self.ndim == 2 else [(None, self)]
11846+
for _, col in cols:
11847+
mask = col.isna().values
11848+
mask = mask[np.argmax(~mask) :]
11849+
if mask.any():
11850+
warnings.warn(
11851+
"The default fill_method='pad' in "
11852+
f"{type(self).__name__}.pct_change is deprecated and will "
11853+
"be removed in a future version. Either fill in any "
11854+
"non-leading NA values prior to calling pct_change or "
11855+
"specify 'fill_method=None' to not fill NA values.",
11856+
FutureWarning,
11857+
stacklevel=find_stack_level(),
11858+
)
11859+
break
1185811860
fill_method = "pad"
1185911861
if limit is lib.no_default:
1186011862
limit = None

pandas/core/groupby/groupby.py

+14-11
Original file line numberDiff line numberDiff line change
@@ -5296,7 +5296,7 @@ def diff(
52965296
def pct_change(
52975297
self,
52985298
periods: int = 1,
5299-
fill_method: FillnaOptions | lib.NoDefault = lib.no_default,
5299+
fill_method: FillnaOptions | None | lib.NoDefault = lib.no_default,
53005300
limit: int | None | lib.NoDefault = lib.no_default,
53015301
freq=None,
53025302
axis: Axis | lib.NoDefault = lib.no_default,
@@ -5348,23 +5348,26 @@ def pct_change(
53485348
goldfish 0.2 0.125
53495349
"""
53505350
# GH#53491
5351-
if fill_method is not lib.no_default or limit is not lib.no_default:
5351+
if fill_method not in (lib.no_default, None) or limit is not lib.no_default:
53525352
warnings.warn(
5353-
"The 'fill_method' and 'limit' keywords in "
5354-
f"{type(self).__name__}.pct_change are deprecated and will be "
5355-
"removed in a future version. Call "
5356-
f"{'bfill' if fill_method in ('backfill', 'bfill') else 'ffill'} "
5357-
"before calling pct_change instead.",
5353+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
5354+
f"{type(self).__name__}.pct_change are deprecated and will be removed "
5355+
"in a future version. Either fill in any non-leading NA values prior "
5356+
"to calling pct_change or specify 'fill_method=None' to not fill NA "
5357+
"values.",
53585358
FutureWarning,
53595359
stacklevel=find_stack_level(),
53605360
)
53615361
if fill_method is lib.no_default:
5362-
if any(grp.isna().values.any() for _, grp in self):
5362+
if limit is lib.no_default and any(
5363+
grp.isna().values.any() for _, grp in self
5364+
):
53635365
warnings.warn(
53645366
"The default fill_method='ffill' in "
5365-
f"{type(self).__name__}.pct_change is deprecated and will be "
5366-
"removed in a future version. Call ffill before calling "
5367-
"pct_change to retain current behavior and silence this warning.",
5367+
f"{type(self).__name__}.pct_change is deprecated and will "
5368+
"be removed in a future version. Either fill in any "
5369+
"non-leading NA values prior to calling pct_change or "
5370+
"specify 'fill_method=None' to not fill NA values.",
53685371
FutureWarning,
53695372
stacklevel=find_stack_level(),
53705373
)

pandas/tests/frame/methods/test_pct_change.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_pct_change_with_nas(
2929
obj = frame_or_series(vals)
3030

3131
msg = (
32-
"The 'fill_method' and 'limit' keywords in "
32+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
3333
f"{type(obj).__name__}.pct_change are deprecated"
3434
)
3535
with tm.assert_produces_warning(FutureWarning, match=msg):
@@ -46,7 +46,7 @@ def test_pct_change_numeric(self):
4646
pnl.iat[2, 3] = 60
4747

4848
msg = (
49-
"The 'fill_method' and 'limit' keywords in "
49+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
5050
"DataFrame.pct_change are deprecated"
5151
)
5252

@@ -59,12 +59,11 @@ def test_pct_change_numeric(self):
5959

6060
def test_pct_change(self, datetime_frame):
6161
msg = (
62-
"The 'fill_method' and 'limit' keywords in "
62+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
6363
"DataFrame.pct_change are deprecated"
6464
)
6565

66-
with tm.assert_produces_warning(FutureWarning, match=msg):
67-
rs = datetime_frame.pct_change(fill_method=None)
66+
rs = datetime_frame.pct_change(fill_method=None)
6867
tm.assert_frame_equal(rs, datetime_frame / datetime_frame.shift(1) - 1)
6968

7069
rs = datetime_frame.pct_change(2)
@@ -110,7 +109,7 @@ def test_pct_change_periods_freq(
110109
self, datetime_frame, freq, periods, fill_method, limit
111110
):
112111
msg = (
113-
"The 'fill_method' and 'limit' keywords in "
112+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
114113
"DataFrame.pct_change are deprecated"
115114
)
116115

@@ -144,11 +143,12 @@ def test_pct_change_with_duplicated_indices(fill_method):
144143
{0: [np.nan, 1, 2, 3, 9, 18], 1: [0, 1, np.nan, 3, 9, 18]}, index=["a", "b"] * 3
145144
)
146145

146+
warn = None if fill_method is None else FutureWarning
147147
msg = (
148-
"The 'fill_method' and 'limit' keywords in "
148+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
149149
"DataFrame.pct_change are deprecated"
150150
)
151-
with tm.assert_produces_warning(FutureWarning, match=msg):
151+
with tm.assert_produces_warning(warn, match=msg):
152152
result = data.pct_change(fill_method=fill_method)
153153

154154
if fill_method is None:

pandas/tests/groupby/transform/test_transform.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,7 @@ def test_pct_change(frame_or_series, freq, periods, fill_method, limit):
10711071
expected = expected.to_frame("vals")
10721072

10731073
msg = (
1074-
"The 'fill_method' and 'limit' keywords in "
1074+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
10751075
f"{type(gb).__name__}.pct_change are deprecated"
10761076
)
10771077
with tm.assert_produces_warning(FutureWarning, match=msg):

pandas/tests/series/methods/test_pct_change.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@
1111
class TestSeriesPctChange:
1212
def test_pct_change(self, datetime_series):
1313
msg = (
14-
"The 'fill_method' and 'limit' keywords in "
14+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
1515
"Series.pct_change are deprecated"
1616
)
1717

18-
with tm.assert_produces_warning(FutureWarning, match=msg):
19-
rs = datetime_series.pct_change(fill_method=None)
18+
rs = datetime_series.pct_change(fill_method=None)
2019
tm.assert_series_equal(rs, datetime_series / datetime_series.shift(1) - 1)
2120

2221
rs = datetime_series.pct_change(2)
@@ -69,7 +68,7 @@ def test_pct_change_periods_freq(
6968
self, freq, periods, fill_method, limit, datetime_series
7069
):
7170
msg = (
72-
"The 'fill_method' and 'limit' keywords in "
71+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
7372
"Series.pct_change are deprecated"
7473
)
7574

@@ -101,8 +100,12 @@ def test_pct_change_with_duplicated_indices(fill_method):
101100
# GH30463
102101
s = Series([np.nan, 1, 2, 3, 9, 18], index=["a", "b"] * 3)
103102

104-
msg = "The 'fill_method' and 'limit' keywords in Series.pct_change are deprecated"
105-
with tm.assert_produces_warning(FutureWarning, match=msg):
103+
warn = None if fill_method is None else FutureWarning
104+
msg = (
105+
"The 'fill_method' keyword being not None and the 'limit' keyword in "
106+
"Series.pct_change are deprecated"
107+
)
108+
with tm.assert_produces_warning(warn, match=msg):
106109
result = s.pct_change(fill_method=fill_method)
107110

108111
expected = Series([np.nan, np.nan, 1.0, 0.5, 2.0, 1.0], index=["a", "b"] * 3)

0 commit comments

Comments
 (0)