Skip to content

Commit 2cb449b

Browse files
committed
reverting
1 parent 59ddbc6 commit 2cb449b

File tree

4 files changed

+110
-90
lines changed

4 files changed

+110
-90
lines changed

pandas/core/generic.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -11144,7 +11144,7 @@ def pct_change(
1114411144
self,
1114511145
periods: int = 1,
1114611146
fill_method: FillnaOptions | None | lib.NoDefault = lib.no_default,
11147-
limit: int | None | lib.NoDefault = lib.no_default,
11147+
limit: int | None = None,
1114811148
freq=None,
1114911149
**kwargs,
1115011150
) -> Self:
@@ -11275,20 +11275,21 @@ def pct_change(
1127511275
GOOG 0.179241 0.094112 NaN
1127611276
APPL -0.252395 -0.011860 NaN
1127711277
"""
11278-
if fill_method is not lib.no_default or limit is not lib.no_default:
11279-
# GH#53491
11278+
# GH#53491: deprecate default fill_method="pad"
11279+
# TODO: In 3.x, change default fill_method=None, then also in 3.x
11280+
# deprecate the fill_method and limit keywords, and finally remove
11281+
# them in 4.x
11282+
if fill_method is lib.no_default:
1128011283
warnings.warn(
11281-
"The 'fill_method' and 'limit' keywords in "
11282-
f"{type(self).__name__}.pct_change are deprecated and will be "
11283-
"removed in a future version. Call fillna directly before "
11284-
"calling pct_change instead.",
11284+
f"The default fill_method='pad' in {type(self).__name__}.pct_change "
11285+
"is deprecated and will be changed to None in a future version of "
11286+
"pandas. Pass fill_method='pad' to retain current behavior or "
11287+
"fill_method=None to adopt the future default and silence this "
11288+
"warning.",
1128511289
FutureWarning,
1128611290
stacklevel=find_stack_level(),
1128711291
)
11288-
if fill_method is lib.no_default:
1128911292
fill_method = "pad"
11290-
if limit is lib.no_default:
11291-
limit = None
1129211293

1129311294
axis = self._get_axis_number(kwargs.pop("axis", "index"))
1129411295
if fill_method is None:

pandas/core/groupby/groupby.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -3946,7 +3946,7 @@ def pct_change(
39463946
self,
39473947
periods: int = 1,
39483948
fill_method: FillnaOptions | lib.NoDefault = lib.no_default,
3949-
limit: int | None | lib.NoDefault = lib.no_default,
3949+
limit: int | None = None,
39503950
freq=None,
39513951
axis: Axis | lib.NoDefault = lib.no_default,
39523952
):
@@ -3958,20 +3958,21 @@ def pct_change(
39583958
Series or DataFrame
39593959
Percentage changes within each group.
39603960
"""
3961-
if fill_method is not lib.no_default or limit is not lib.no_default:
3962-
# GH#53491
3961+
# GH#53491: deprecate default fill_method="ffill"
3962+
# TODO: In 3.x, change default fill_method=None, then also in 3.x
3963+
# deprecate the fill_method and limit keywords, and finally remove
3964+
# them in 4.x
3965+
if fill_method is lib.no_default:
39633966
warnings.warn(
3964-
"The 'fill_method' and 'limit' keywords in "
3965-
f"{type(self).__name__}.pct_change are deprecated and will be "
3966-
"removed in a future version. Call fillna directly before "
3967-
"calling pct_change instead.",
3967+
f"The default fill_method='ffill' in {type(self).__name__}.pct_change "
3968+
"is deprecated and will be changed to None in a future version of "
3969+
"pandas. Pass fill_method='ffill' to retain current behavior or "
3970+
"fill_method=None to adopt the future default and silence this "
3971+
"warning.",
39683972
FutureWarning,
39693973
stacklevel=find_stack_level(),
39703974
)
3971-
if fill_method is lib.no_default:
39723975
fill_method = "ffill"
3973-
if limit is lib.no_default:
3974-
limit = None
39753976

39763977
if axis is not lib.no_default:
39773978
axis = self.obj._get_axis_number(axis)

pandas/tests/frame/methods/test_pct_change.py

+23-55
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
class TestDataFramePctChange:
1212
@pytest.mark.parametrize(
13-
"periods, fill_method, limit, exp",
13+
"periods,fill_method,limit,exp",
1414
[
1515
(1, "ffill", None, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, 0]),
1616
(1, "ffill", 1, [np.nan, np.nan, np.nan, 1, 1, 1.5, 0, np.nan]),
@@ -28,12 +28,7 @@ def test_pct_change_with_nas(
2828
vals = [np.nan, np.nan, 1, 2, 4, 10, np.nan, np.nan]
2929
obj = frame_or_series(vals)
3030

31-
msg = (
32-
"The 'fill_method' and 'limit' keywords in "
33-
f"{type(obj).__name__}.pct_change are deprecated"
34-
)
35-
with tm.assert_produces_warning(FutureWarning, match=msg):
36-
res = obj.pct_change(periods=periods, fill_method=fill_method, limit=limit)
31+
res = obj.pct_change(periods=periods, fill_method=fill_method, limit=limit)
3732
tm.assert_equal(res, frame_or_series(exp))
3833

3934
def test_pct_change_numeric(self):
@@ -45,49 +40,41 @@ def test_pct_change_numeric(self):
4540
pnl.iat[1, 1] = np.nan
4641
pnl.iat[2, 3] = 60
4742

48-
msg = (
49-
"The 'fill_method' and 'limit' keywords in "
50-
"DataFrame.pct_change are deprecated"
51-
)
52-
5343
for axis in range(2):
5444
expected = pnl.ffill(axis=axis) / pnl.ffill(axis=axis).shift(axis=axis) - 1
55-
56-
with tm.assert_produces_warning(FutureWarning, match=msg):
57-
result = pnl.pct_change(axis=axis, fill_method="pad")
45+
result = pnl.pct_change(axis=axis, fill_method="pad")
5846
tm.assert_frame_equal(result, expected)
5947

6048
def test_pct_change(self, datetime_frame):
61-
msg = (
62-
"The 'fill_method' and 'limit' keywords in "
63-
"DataFrame.pct_change are deprecated"
64-
)
49+
msg = "The default fill_method='pad' in DataFrame.pct_change is deprecated"
6550

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

70-
rs = datetime_frame.pct_change(2)
54+
with tm.assert_produces_warning(FutureWarning, match=msg):
55+
rs = datetime_frame.pct_change(2)
7156
filled = datetime_frame.fillna(method="pad")
7257
tm.assert_frame_equal(rs, filled / filled.shift(2) - 1)
7358

74-
with tm.assert_produces_warning(FutureWarning, match=msg):
75-
rs = datetime_frame.pct_change(fill_method="bfill", limit=1)
59+
rs = datetime_frame.pct_change(fill_method="bfill", limit=1)
7660
filled = datetime_frame.fillna(method="bfill", limit=1)
7761
tm.assert_frame_equal(rs, filled / filled.shift(1) - 1)
7862

79-
rs = datetime_frame.pct_change(freq="5D")
63+
with tm.assert_produces_warning(FutureWarning, match=msg):
64+
rs = datetime_frame.pct_change(freq="5D")
8065
filled = datetime_frame.fillna(method="pad")
8166
tm.assert_frame_equal(
8267
rs, (filled / filled.shift(freq="5D") - 1).reindex_like(filled)
8368
)
8469

8570
def test_pct_change_shift_over_nas(self):
8671
s = Series([1.0, 1.5, np.nan, 2.5, 3.0])
87-
8872
df = DataFrame({"a": s, "b": s})
8973

90-
chg = df.pct_change()
74+
msg = "The default fill_method='pad' in DataFrame.pct_change is deprecated"
75+
with tm.assert_produces_warning(FutureWarning, match=msg):
76+
chg = df.pct_change()
77+
9178
expected = Series([np.nan, 0.5, 0.0, 2.5 / 1.5 - 1, 0.2])
9279
edf = DataFrame({"a": expected, "b": expected})
9380
tm.assert_frame_equal(chg, edf)
@@ -106,31 +93,18 @@ def test_pct_change_shift_over_nas(self):
10693
def test_pct_change_periods_freq(
10794
self, datetime_frame, freq, periods, fill_method, limit
10895
):
109-
msg = (
110-
"The 'fill_method' and 'limit' keywords in "
111-
"DataFrame.pct_change are deprecated"
112-
)
113-
11496
# GH#7292
115-
with tm.assert_produces_warning(FutureWarning, match=msg):
116-
rs_freq = datetime_frame.pct_change(
117-
freq=freq, fill_method=fill_method, limit=limit
118-
)
119-
with tm.assert_produces_warning(FutureWarning, match=msg):
120-
rs_periods = datetime_frame.pct_change(
121-
periods, fill_method=fill_method, limit=limit
122-
)
97+
rs_freq = datetime_frame.pct_change(
98+
freq=freq, fill_method=fill_method, limit=limit
99+
)
100+
rs_periods = datetime_frame.pct_change(
101+
periods, fill_method=fill_method, limit=limit
102+
)
123103
tm.assert_frame_equal(rs_freq, rs_periods)
124104

125105
empty_ts = DataFrame(index=datetime_frame.index, columns=datetime_frame.columns)
126-
with tm.assert_produces_warning(FutureWarning, match=msg):
127-
rs_freq = empty_ts.pct_change(
128-
freq=freq, fill_method=fill_method, limit=limit
129-
)
130-
with tm.assert_produces_warning(FutureWarning, match=msg):
131-
rs_periods = empty_ts.pct_change(
132-
periods, fill_method=fill_method, limit=limit
133-
)
106+
rs_freq = empty_ts.pct_change(freq=freq, fill_method=fill_method, limit=limit)
107+
rs_periods = empty_ts.pct_change(periods, fill_method=fill_method, limit=limit)
134108
tm.assert_frame_equal(rs_freq, rs_periods)
135109

136110

@@ -140,13 +114,7 @@ def test_pct_change_with_duplicated_indices(fill_method):
140114
data = DataFrame(
141115
{0: [np.nan, 1, 2, 3, 9, 18], 1: [0, 1, np.nan, 3, 9, 18]}, index=["a", "b"] * 3
142116
)
143-
144-
msg = (
145-
"The 'fill_method' and 'limit' keywords in "
146-
"DataFrame.pct_change are deprecated"
147-
)
148-
with tm.assert_produces_warning(FutureWarning, match=msg):
149-
result = data.pct_change(fill_method=fill_method)
117+
result = data.pct_change(fill_method=fill_method)
150118

151119
if fill_method is None:
152120
second_column = [np.nan, np.inf, np.nan, np.nan, 2.0, 1.0]

pandas/tests/groupby/transform/test_transform.py

+65-15
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,18 @@ def test_transform_axis_1(request, transformation_func):
169169
msg = "DataFrame.groupby with axis=1 is deprecated"
170170
with tm.assert_produces_warning(FutureWarning, match=msg):
171171
gb = df.groupby([0, 0, 1], axis=1)
172-
result = gb.transform(transformation_func, *args)
173-
expected = df.T.groupby([0, 0, 1]).transform(transformation_func, *args).T
172+
173+
pct_change_msg = (
174+
"The default fill_method='ffill' in DataFrameGroupBy.pct_change is deprecated"
175+
)
176+
if transformation_func == "pct_change":
177+
with tm.assert_produces_warning(FutureWarning, match=pct_change_msg):
178+
result = gb.transform("pct_change", *args)
179+
with tm.assert_produces_warning(FutureWarning, match=pct_change_msg):
180+
expected = df.T.groupby([0, 0, 1]).transform("pct_change", *args).T
181+
else:
182+
result = gb.transform(transformation_func, *args)
183+
expected = df.T.groupby([0, 0, 1]).transform(transformation_func, *args).T
174184

175185
if transformation_func in ["diff", "shift"]:
176186
# Result contains nans, so transpose coerces to float
@@ -404,11 +414,25 @@ def mock_op(x):
404414
test_op = lambda x: x.transform(transformation_func)
405415
mock_op = lambda x: getattr(x, transformation_func)()
406416

407-
result = test_op(df.groupby("A"))
417+
msg = "The default fill_method='pad' in DataFrame.pct_change is deprecated"
418+
groupby_msg = (
419+
"The default fill_method='ffill' in DataFrameGroupBy.pct_change is deprecated"
420+
)
421+
422+
if transformation_func == "pct_change":
423+
with tm.assert_produces_warning(FutureWarning, match=groupby_msg):
424+
result = test_op(df.groupby("A"))
425+
else:
426+
result = test_op(df.groupby("A"))
427+
408428
# pass the group in same order as iterating `for ... in df.groupby(...)`
409429
# but reorder to match df's index since this is a transform
410430
groups = [df[["B"]].iloc[4:6], df[["B"]].iloc[6:], df[["B"]].iloc[:4]]
411-
expected = concat([mock_op(g) for g in groups]).sort_index()
431+
if transformation_func == "pct_change":
432+
with tm.assert_produces_warning(FutureWarning, match=msg):
433+
expected = concat([mock_op(g) for g in groups]).sort_index()
434+
else:
435+
expected = concat([mock_op(g) for g in groups]).sort_index()
412436
# sort_index does not preserve the freq
413437
expected = expected.set_axis(df.index)
414438

@@ -969,14 +993,9 @@ def test_pct_change(frame_or_series, freq, periods, fill_method, limit):
969993
else:
970994
expected = expected.to_frame("vals")
971995

972-
msg = (
973-
"The 'fill_method' and 'limit' keywords in "
974-
f"{type(gb).__name__}.pct_change are deprecated"
996+
result = gb.pct_change(
997+
periods=periods, fill_method=fill_method, limit=limit, freq=freq
975998
)
976-
with tm.assert_produces_warning(FutureWarning, match=msg):
977-
result = gb.pct_change(
978-
periods=periods, fill_method=fill_method, limit=limit, freq=freq
979-
)
980999
tm.assert_equal(result, expected)
9811000

9821001

@@ -1394,13 +1413,21 @@ def test_null_group_str_transformer(request, dropna, transformation_func):
13941413
args = get_groupby_method_args(transformation_func, df)
13951414
gb = df.groupby("A", dropna=dropna)
13961415

1416+
msg = "The default fill_method='pad' in DataFrame.pct_change is deprecated"
1417+
groupby_msg = (
1418+
"The default fill_method='ffill' in DataFrameGroupBy.pct_change is deprecated"
1419+
)
1420+
13971421
buffer = []
13981422
for k, (idx, group) in enumerate(gb):
13991423
if transformation_func == "cumcount":
14001424
# DataFrame has no cumcount method
14011425
res = DataFrame({"B": range(len(group))}, index=group.index)
14021426
elif transformation_func == "ngroup":
14031427
res = DataFrame(len(group) * [k], index=group.index, columns=["B"])
1428+
elif transformation_func == "pct_change":
1429+
with tm.assert_produces_warning(FutureWarning, match=msg):
1430+
res = getattr(group[["B"]], "pct_change")(*args)
14041431
else:
14051432
res = getattr(group[["B"]], transformation_func)(*args)
14061433
buffer.append(res)
@@ -1413,7 +1440,11 @@ def test_null_group_str_transformer(request, dropna, transformation_func):
14131440
# ngroup/cumcount always returns a Series as it counts the groups, not values
14141441
expected = expected["B"].rename(None)
14151442

1416-
result = gb.transform(transformation_func, *args)
1443+
if transformation_func == "pct_change":
1444+
with tm.assert_produces_warning(FutureWarning, match=groupby_msg):
1445+
result = gb.transform("pct_change", *args)
1446+
else:
1447+
result = gb.transform(transformation_func, *args)
14171448

14181449
tm.assert_equal(result, expected)
14191450

@@ -1465,13 +1496,21 @@ def test_null_group_str_transformer_series(dropna, transformation_func):
14651496
args = get_groupby_method_args(transformation_func, ser)
14661497
gb = ser.groupby([1, 1, np.nan], dropna=dropna)
14671498

1499+
msg = "The default fill_method='pad' in Series.pct_change is deprecated"
1500+
groupby_msg = (
1501+
"The default fill_method='ffill' in SeriesGroupBy.pct_change is deprecated"
1502+
)
1503+
14681504
buffer = []
14691505
for k, (idx, group) in enumerate(gb):
14701506
if transformation_func == "cumcount":
14711507
# Series has no cumcount method
14721508
res = Series(range(len(group)), index=group.index)
14731509
elif transformation_func == "ngroup":
14741510
res = Series(k, index=group.index)
1511+
elif transformation_func == "pct_change":
1512+
with tm.assert_produces_warning(FutureWarning, match=msg):
1513+
res = getattr(group, "pct_change")(*args)
14751514
else:
14761515
res = getattr(group, transformation_func)(*args)
14771516
buffer.append(res)
@@ -1480,7 +1519,10 @@ def test_null_group_str_transformer_series(dropna, transformation_func):
14801519
buffer.append(Series([np.nan], index=[3], dtype=dtype))
14811520
expected = concat(buffer)
14821521

1483-
with tm.assert_produces_warning(None):
1522+
if transformation_func == "pct_change":
1523+
with tm.assert_produces_warning(FutureWarning, match=groupby_msg):
1524+
result = gb.transform("pct_change", *args)
1525+
else:
14841526
result = gb.transform(transformation_func, *args)
14851527

14861528
tm.assert_equal(result, expected)
@@ -1523,6 +1565,14 @@ def test_as_index_no_change(keys, df, groupby_func):
15231565
args = get_groupby_method_args(groupby_func, df)
15241566
gb_as_index_true = df.groupby(keys, as_index=True)
15251567
gb_as_index_false = df.groupby(keys, as_index=False)
1526-
result = gb_as_index_true.transform(groupby_func, *args)
1527-
expected = gb_as_index_false.transform(groupby_func, *args)
1568+
1569+
msg = "The default fill_method='ffill' in DataFrameGroupBy.pct_change is deprecated"
1570+
if groupby_func == "pct_change":
1571+
with tm.assert_produces_warning(FutureWarning, match=msg):
1572+
result = gb_as_index_true.transform("pct_change", *args)
1573+
with tm.assert_produces_warning(FutureWarning, match=msg):
1574+
expected = gb_as_index_false.transform("pct_change", *args)
1575+
else:
1576+
result = gb_as_index_true.transform(groupby_func, *args)
1577+
expected = gb_as_index_false.transform(groupby_func, *args)
15281578
tm.assert_equal(result, expected)

0 commit comments

Comments
 (0)