diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 939b3c191c4a1..24cd41383e9d7 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -682,6 +682,7 @@ Deprecations - Deprecated passing arguments as positional in :meth:`DataFrame.clip` and :meth:`Series.clip` (other than ``"upper"`` and ``"lower"``) (:issue:`41485`) - Deprecated special treatment of lists with first element a Categorical in the :class:`DataFrame` constructor; pass as ``pd.DataFrame({col: categorical, ...})`` instead (:issue:`38845`) - Deprecated passing arguments as positional (except for ``"method"``) in :meth:`DataFrame.interpolate` and :meth:`Series.interpolate` (:issue:`41485`) +- Deprecated passing arguments as positional in :meth:`DataFrame.ffill`, :meth:`Series.ffill`, :meth:`DataFrame.bfill`, and :meth:`Series.bfill` (:issue:`41485`) - Deprecated passing arguments as positional in :meth:`DataFrame.sort_values` (other than ``"by"``) and :meth:`Series.sort_values` (:issue:`41485`) - Deprecated passing arguments as positional in :meth:`DataFrame.dropna` and :meth:`Series.dropna` (:issue:`41485`) - Deprecated passing arguments as positional in :meth:`DataFrame.set_index` (other than ``"keys"``) (:issue:`41485`) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index bc27244c63954..75d2f4c591053 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -10646,6 +10646,26 @@ def values(self) -> np.ndarray: self._consolidate_inplace() return self._mgr.as_array(transpose=True) + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def ffill( + self: DataFrame, + axis: None | Axis = None, + inplace: bool = False, + limit: None | int = None, + downcast=None, + ) -> DataFrame | None: + return super().ffill(axis, inplace, limit, downcast) + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def bfill( + self: DataFrame, + axis: None | Axis = None, + inplace: bool = False, + limit: None | int = None, + downcast=None, + ) -> DataFrame | None: + return super().bfill(axis, inplace, limit, downcast) + @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "lower", "upper"] ) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 32ecb9f8f76f5..8bbfa1f1db680 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6392,47 +6392,6 @@ def fillna( else: return result.__finalize__(self, method="fillna") - @overload - def ffill( - self: FrameOrSeries, - axis: None | Axis = ..., - inplace: Literal[False] = ..., - limit: None | int = ..., - downcast=..., - ) -> FrameOrSeries: - ... - - @overload - def ffill( - self: FrameOrSeries, - axis: None | Axis, - inplace: Literal[True], - limit: None | int = ..., - downcast=..., - ) -> None: - ... - - @overload - def ffill( - self: FrameOrSeries, - *, - inplace: Literal[True], - limit: None | int = ..., - downcast=..., - ) -> None: - ... - - @overload - def ffill( - self: FrameOrSeries, - axis: None | Axis = ..., - inplace: bool_t = ..., - limit: None | int = ..., - downcast=..., - ) -> FrameOrSeries | None: - ... - - @final @doc(klass=_shared_doc_kwargs["klass"]) def ffill( self: FrameOrSeries, @@ -6455,47 +6414,6 @@ def ffill( pad = ffill - @overload - def bfill( - self: FrameOrSeries, - axis: None | Axis = ..., - inplace: Literal[False] = ..., - limit: None | int = ..., - downcast=..., - ) -> FrameOrSeries: - ... - - @overload - def bfill( - self: FrameOrSeries, - axis: None | Axis, - inplace: Literal[True], - limit: None | int = ..., - downcast=..., - ) -> None: - ... - - @overload - def bfill( - self: FrameOrSeries, - *, - inplace: Literal[True], - limit: None | int = ..., - downcast=..., - ) -> None: - ... - - @overload - def bfill( - self: FrameOrSeries, - axis: None | Axis = ..., - inplace: bool_t = ..., - limit: None | int = ..., - downcast=..., - ) -> FrameOrSeries | None: - ... - - @final @doc(klass=_shared_doc_kwargs["klass"]) def bfill( self: FrameOrSeries, diff --git a/pandas/core/series.py b/pandas/core/series.py index ac514e6ad787c..686e6966d8e24 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -5292,6 +5292,26 @@ def to_period(self, freq=None, copy=True) -> Series: self, method="to_period" ) + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def ffill( + self: Series, + axis: None | Axis = None, + inplace: bool = False, + limit: None | int = None, + downcast=None, + ) -> Series | None: + return super().ffill(axis, inplace, limit, downcast) + + @deprecate_nonkeyword_arguments(version=None, allowed_args=["self"]) + def bfill( + self: Series, + axis: None | Axis = None, + inplace: bool = False, + limit: None | int = None, + downcast=None, + ) -> Series | None: + return super().bfill(axis, inplace, limit, downcast) + @deprecate_nonkeyword_arguments( version=None, allowed_args=["self", "lower", "upper"] ) diff --git a/pandas/tests/frame/methods/test_fillna.py b/pandas/tests/frame/methods/test_fillna.py index cb01de11a4be9..065d074eef6e8 100644 --- a/pandas/tests/frame/methods/test_fillna.py +++ b/pandas/tests/frame/methods/test_fillna.py @@ -326,6 +326,18 @@ def test_ffill(self, datetime_frame): datetime_frame.ffill(), datetime_frame.fillna(method="ffill") ) + def test_ffill_pos_args_deprecation(self): + # https://github.com/pandas-dev/pandas/issues/41485 + df = DataFrame({"a": [1, 2, 3]}) + msg = ( + r"In a future version of pandas all arguments of DataFrame.ffill " + r"will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.ffill(0) + expected = DataFrame({"a": [1, 2, 3]}) + tm.assert_frame_equal(result, expected) + def test_bfill(self, datetime_frame): datetime_frame["A"][:5] = np.nan datetime_frame["A"][-5:] = np.nan @@ -334,6 +346,18 @@ def test_bfill(self, datetime_frame): datetime_frame.bfill(), datetime_frame.fillna(method="bfill") ) + def test_bfill_pos_args_deprecation(self): + # https://github.com/pandas-dev/pandas/issues/41485 + df = DataFrame({"a": [1, 2, 3]}) + msg = ( + r"In a future version of pandas all arguments of DataFrame.bfill " + r"will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.bfill(0) + expected = DataFrame({"a": [1, 2, 3]}) + tm.assert_frame_equal(result, expected) + def test_frame_pad_backfill_limit(self): index = np.arange(10) df = DataFrame(np.random.randn(10, 4), index=index) diff --git a/pandas/tests/series/methods/test_fillna.py b/pandas/tests/series/methods/test_fillna.py index 97804e0fef8b9..82c52bdaa29d7 100644 --- a/pandas/tests/series/methods/test_fillna.py +++ b/pandas/tests/series/methods/test_fillna.py @@ -777,6 +777,18 @@ def test_ffill(self): ts[2] = np.NaN tm.assert_series_equal(ts.ffill(), ts.fillna(method="ffill")) + def test_ffill_pos_args_deprecation(self): + # https://github.com/pandas-dev/pandas/issues/41485 + ser = Series([1, 2, 3]) + msg = ( + r"In a future version of pandas all arguments of Series.ffill " + r"will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = ser.ffill(0) + expected = Series([1, 2, 3]) + tm.assert_series_equal(result, expected) + def test_ffill_mixed_dtypes_without_missing_data(self): # GH#14956 series = Series([datetime(2015, 1, 1, tzinfo=pytz.utc), 1]) @@ -788,6 +800,18 @@ def test_bfill(self): ts[2] = np.NaN tm.assert_series_equal(ts.bfill(), ts.fillna(method="bfill")) + def test_bfill_pos_args_deprecation(self): + # https://github.com/pandas-dev/pandas/issues/41485 + ser = Series([1, 2, 3]) + msg = ( + r"In a future version of pandas all arguments of Series.bfill " + r"will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = ser.bfill(0) + expected = Series([1, 2, 3]) + tm.assert_series_equal(result, expected) + def test_pad_nan(self): x = Series( [np.nan, 1.0, np.nan, 3.0, np.nan], ["z", "a", "b", "c", "d"], dtype=float