Skip to content

Commit 2c04ce9

Browse files
jbrockmendelim-vinicius
authored and
im-vinicius
committed
DEPR: NDFrame.interpolate with ffill/bfill methods (pandas-dev#53607)
* DEPR: NDFrame.interpolate with ffill/bfill methods * update doctest
1 parent cdc76fb commit 2c04ce9

File tree

5 files changed

+63
-41
lines changed

5 files changed

+63
-41
lines changed

doc/source/whatsnew/v2.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ Deprecations
286286
- Deprecated option "mode.use_inf_as_na", convert inf entries to ``NaN`` before instead (:issue:`51684`)
287287
- Deprecated positional indexing on :class:`Series` with :meth:`Series.__getitem__` and :meth:`Series.__setitem__`, in a future version ``ser[item]`` will *always* interpret ``item`` as a label, not a position (:issue:`50617`)
288288
- Deprecated the "method" and "limit" keywords on :meth:`Series.fillna`, :meth:`DataFrame.fillna`, :meth:`SeriesGroupBy.fillna`, :meth:`DataFrameGroupBy.fillna`, and :meth:`Resampler.fillna`, use ``obj.bfill()`` or ``obj.ffill()`` instead (:issue:`53394`)
289+
- Deprecated values "pad", "ffill", "bfill", "backfill" for :meth:`Series.interpolate` and :meth:`DataFrame.interpolate`, use ``obj.ffill()`` or ``obj.bfill()`` instead (:issue:`53581`)
289290
-
290291

291292
.. ---------------------------------------------------------------------------

pandas/core/generic.py

+11-29
Original file line numberDiff line numberDiff line change
@@ -7807,35 +7807,6 @@ def interpolate(
78077807
3 3.0
78087808
dtype: float64
78097809
7810-
Filling in ``NaN`` in a Series by padding, but filling at most two
7811-
consecutive ``NaN`` at a time.
7812-
7813-
>>> s = pd.Series([np.nan, "single_one", np.nan,
7814-
... "fill_two_more", np.nan, np.nan, np.nan,
7815-
... 4.71, np.nan])
7816-
>>> s
7817-
0 NaN
7818-
1 single_one
7819-
2 NaN
7820-
3 fill_two_more
7821-
4 NaN
7822-
5 NaN
7823-
6 NaN
7824-
7 4.71
7825-
8 NaN
7826-
dtype: object
7827-
>>> s.interpolate(method='pad', limit=2)
7828-
0 NaN
7829-
1 single_one
7830-
2 single_one
7831-
3 fill_two_more
7832-
4 fill_two_more
7833-
5 fill_two_more
7834-
6 NaN
7835-
7 4.71
7836-
8 4.71
7837-
dtype: object
7838-
78397810
Filling in ``NaN`` in a Series via polynomial interpolation or splines:
78407811
Both 'polynomial' and 'spline' methods require that you also specify
78417812
an ``order`` (int).
@@ -7900,6 +7871,17 @@ def interpolate(
79007871
return None
79017872
return self.copy()
79027873

7874+
if not isinstance(method, str):
7875+
raise ValueError("'method' should be a string, not None.")
7876+
elif method.lower() in fillna_methods:
7877+
# GH#53581
7878+
warnings.warn(
7879+
f"{type(self).__name__}.interpolate with method={method} is "
7880+
"deprecated and will raise in a future version. "
7881+
"Use obj.ffill() or obj.bfill() instead.",
7882+
FutureWarning,
7883+
stacklevel=find_stack_level(),
7884+
)
79037885
if method not in fillna_methods:
79047886
axis = self._info_axis_number
79057887

pandas/tests/copy_view/test_interp_fillna.py

+18-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ def test_interpolate_no_op(using_copy_on_write, method):
2020
df = DataFrame({"a": [1, 2]})
2121
df_orig = df.copy()
2222

23-
result = df.interpolate(method=method)
23+
warn = None
24+
if method == "pad":
25+
warn = FutureWarning
26+
msg = "DataFrame.interpolate with method=pad is deprecated"
27+
with tm.assert_produces_warning(warn, match=msg):
28+
result = df.interpolate(method=method)
2429

2530
if using_copy_on_write:
2631
assert np.shares_memory(get_array(result, "a"), get_array(df, "a"))
@@ -125,7 +130,9 @@ def test_interpolate_cleaned_fill_method(using_copy_on_write):
125130
def test_interpolate_object_convert_no_op(using_copy_on_write):
126131
df = DataFrame({"a": ["a", "b", "c"], "b": 1})
127132
arr_a = get_array(df, "a")
128-
df.interpolate(method="pad", inplace=True)
133+
msg = "DataFrame.interpolate with method=pad is deprecated"
134+
with tm.assert_produces_warning(FutureWarning, match=msg):
135+
df.interpolate(method="pad", inplace=True)
129136

130137
# Now CoW makes a copy, it should not!
131138
if using_copy_on_write:
@@ -136,7 +143,9 @@ def test_interpolate_object_convert_no_op(using_copy_on_write):
136143
def test_interpolate_object_convert_copies(using_copy_on_write):
137144
df = DataFrame({"a": Series([1, 2], dtype=object), "b": 1})
138145
arr_a = get_array(df, "a")
139-
df.interpolate(method="pad", inplace=True)
146+
msg = "DataFrame.interpolate with method=pad is deprecated"
147+
with tm.assert_produces_warning(FutureWarning, match=msg):
148+
df.interpolate(method="pad", inplace=True)
140149

141150
if using_copy_on_write:
142151
assert df._mgr._has_no_reference(0)
@@ -146,7 +155,9 @@ def test_interpolate_object_convert_copies(using_copy_on_write):
146155
def test_interpolate_downcast(using_copy_on_write):
147156
df = DataFrame({"a": [1, np.nan, 2.5], "b": 1})
148157
arr_a = get_array(df, "a")
149-
df.interpolate(method="pad", inplace=True, downcast="infer")
158+
msg = "DataFrame.interpolate with method=pad is deprecated"
159+
with tm.assert_produces_warning(FutureWarning, match=msg):
160+
df.interpolate(method="pad", inplace=True, downcast="infer")
150161

151162
if using_copy_on_write:
152163
assert df._mgr._has_no_reference(0)
@@ -158,7 +169,9 @@ def test_interpolate_downcast_reference_triggers_copy(using_copy_on_write):
158169
df_orig = df.copy()
159170
arr_a = get_array(df, "a")
160171
view = df[:]
161-
df.interpolate(method="pad", inplace=True, downcast="infer")
172+
msg = "DataFrame.interpolate with method=pad is deprecated"
173+
with tm.assert_produces_warning(FutureWarning, match=msg):
174+
df.interpolate(method="pad", inplace=True, downcast="infer")
162175

163176
if using_copy_on_write:
164177
assert df._mgr._has_no_reference(0)

pandas/tests/frame/methods/test_interpolate.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,9 @@ def test_interp_fillna_methods(self, request, axis, method, using_array_manager)
436436
)
437437
method2 = method if method != "pad" else "ffill"
438438
expected = getattr(df, method2)(axis=axis)
439-
result = df.interpolate(method=method, axis=axis)
439+
msg = f"DataFrame.interpolate with method={method} is deprecated"
440+
with tm.assert_produces_warning(FutureWarning, match=msg):
441+
result = df.interpolate(method=method, axis=axis)
440442
tm.assert_frame_equal(result, expected)
441443

442444
def test_interpolate_empty_df(self):

pandas/tests/series/methods/test_interpolate.py

+30-6
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,8 @@ def test_interp_invalid_method(self, invalid_method):
347347
s = Series([1, 3, np.nan, 12, np.nan, 25])
348348

349349
msg = f"method must be one of.* Got '{invalid_method}' instead"
350+
if invalid_method is None:
351+
msg = "'method' should be a string, not None"
350352
with pytest.raises(ValueError, match=msg):
351353
s.interpolate(method=invalid_method)
352354

@@ -360,8 +362,10 @@ def test_interp_invalid_method_and_value(self):
360362
ser = Series([1, 3, np.nan, 12, np.nan, 25])
361363

362364
msg = "Cannot pass both fill_value and method"
365+
msg2 = "Series.interpolate with method=pad"
363366
with pytest.raises(ValueError, match=msg):
364-
ser.interpolate(fill_value=3, method="pad")
367+
with tm.assert_produces_warning(FutureWarning, match=msg2):
368+
ser.interpolate(fill_value=3, method="pad")
365369

366370
def test_interp_limit_forward(self):
367371
s = Series([1, 3, np.nan, np.nan, np.nan, 11])
@@ -470,8 +474,10 @@ def test_interp_limit_direction_raises(self, method, limit_direction, expected):
470474
s = Series([1, 2, 3])
471475

472476
msg = f"`limit_direction` must be '{expected}' for method `{method}`"
477+
msg2 = "Series.interpolate with method="
473478
with pytest.raises(ValueError, match=msg):
474-
s.interpolate(method=method, limit_direction=limit_direction)
479+
with tm.assert_produces_warning(FutureWarning, match=msg2):
480+
s.interpolate(method=method, limit_direction=limit_direction)
475481

476482
@pytest.mark.parametrize(
477483
"data, expected_data, kwargs",
@@ -513,7 +519,9 @@ def test_interp_limit_area_with_pad(self, data, expected_data, kwargs):
513519

514520
s = Series(data)
515521
expected = Series(expected_data)
516-
result = s.interpolate(**kwargs)
522+
msg = "Series.interpolate with method=pad"
523+
with tm.assert_produces_warning(FutureWarning, match=msg):
524+
result = s.interpolate(**kwargs)
517525
tm.assert_series_equal(result, expected)
518526

519527
@pytest.mark.parametrize(
@@ -546,7 +554,9 @@ def test_interp_limit_area_with_backfill(self, data, expected_data, kwargs):
546554

547555
s = Series(data)
548556
expected = Series(expected_data)
549-
result = s.interpolate(**kwargs)
557+
msg = "Series.interpolate with method=bfill"
558+
with tm.assert_produces_warning(FutureWarning, match=msg):
559+
result = s.interpolate(**kwargs)
550560
tm.assert_series_equal(result, expected)
551561

552562
def test_interp_limit_direction(self):
@@ -642,7 +652,15 @@ def test_interp_datetime64(self, method, tz_naive_fixture):
642652
df = Series(
643653
[1, np.nan, 3], index=date_range("1/1/2000", periods=3, tz=tz_naive_fixture)
644654
)
645-
result = df.interpolate(method=method)
655+
warn = None if method == "nearest" else FutureWarning
656+
msg = "Series.interpolate with method=pad is deprecated"
657+
with tm.assert_produces_warning(warn, match=msg):
658+
result = df.interpolate(method=method)
659+
if warn is not None:
660+
# check the "use ffill instead" is equivalent
661+
alt = df.ffill()
662+
tm.assert_series_equal(result, alt)
663+
646664
expected = Series(
647665
[1.0, 1.0, 3.0],
648666
index=date_range("1/1/2000", periods=3, tz=tz_naive_fixture),
@@ -654,7 +672,13 @@ def test_interp_pad_datetime64tz_values(self):
654672
dti = date_range("2015-04-05", periods=3, tz="US/Central")
655673
ser = Series(dti)
656674
ser[1] = pd.NaT
657-
result = ser.interpolate(method="pad")
675+
676+
msg = "Series.interpolate with method=pad is deprecated"
677+
with tm.assert_produces_warning(FutureWarning, match=msg):
678+
result = ser.interpolate(method="pad")
679+
# check the "use ffill instead" is equivalent
680+
alt = ser.ffill()
681+
tm.assert_series_equal(result, alt)
658682

659683
expected = Series(dti)
660684
expected[1] = expected[0]

0 commit comments

Comments
 (0)