From 74bdb077a5a8e7e3283cc617a84c239f508feca8 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 1 Jun 2023 16:10:10 -0700 Subject: [PATCH 1/7] DEPR: fillna method kwd --- .../comparison/includes/missing.rst | 2 +- doc/source/user_guide/basics.rst | 4 +- doc/source/user_guide/missing_data.rst | 6 +- doc/source/whatsnew/v0.10.0.rst | 1 + doc/source/whatsnew/v2.1.0.rst | 1 + pandas/core/generic.py | 152 ++++++++++++------ pandas/core/groupby/generic.py | 56 ++----- pandas/core/groupby/groupby.py | 48 ++++++ pandas/core/resample.py | 8 + pandas/tests/arrays/test_datetimes.py | 4 +- pandas/tests/extension/base/missing.py | 10 +- pandas/tests/extension/test_sparse.py | 10 +- pandas/tests/frame/methods/test_align.py | 6 +- pandas/tests/frame/methods/test_fillna.py | 95 +++++++---- .../tests/frame/methods/test_interpolate.py | 3 +- pandas/tests/frame/methods/test_pct_change.py | 6 +- pandas/tests/frame/methods/test_replace.py | 7 +- pandas/tests/generic/test_finalize.py | 3 + pandas/tests/groupby/test_missing.py | 4 +- .../tests/groupby/transform/test_transform.py | 8 +- pandas/tests/resample/test_resample_api.py | 14 +- pandas/tests/series/methods/test_align.py | 6 +- pandas/tests/series/methods/test_fillna.py | 10 +- .../tests/series/methods/test_pct_change.py | 6 +- pandas/tests/series/methods/test_reindex.py | 2 +- .../moments/test_moments_consistency_ewm.py | 11 +- pandas/tests/window/test_ewm.py | 2 +- 27 files changed, 319 insertions(+), 166 deletions(-) diff --git a/doc/source/getting_started/comparison/includes/missing.rst b/doc/source/getting_started/comparison/includes/missing.rst index 341c7d5498d82..ab5d90166e7b0 100644 --- a/doc/source/getting_started/comparison/includes/missing.rst +++ b/doc/source/getting_started/comparison/includes/missing.rst @@ -19,7 +19,7 @@ Forward fill from previous rows .. ipython:: python - outer_join.fillna(method="ffill") + outer_join.ffill() Replace missing values with a specified value ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/source/user_guide/basics.rst b/doc/source/user_guide/basics.rst index a8afb05bc5200..eec33afb9ab95 100644 --- a/doc/source/user_guide/basics.rst +++ b/doc/source/user_guide/basics.rst @@ -1377,12 +1377,12 @@ These methods require that the indexes are **ordered** increasing or decreasing. Note that the same result could have been achieved using -:ref:`fillna ` (except for ``method='nearest'``) or +:ref:`ffill ` (except for ``method='nearest'``) or :ref:`interpolate `: .. ipython:: python - ts2.reindex(ts.index).fillna(method="ffill") + ts2.reindex(ts.index).ffill() :meth:`~Series.reindex` will raise a ValueError if the index is not monotonically increasing or decreasing. :meth:`~Series.fillna` and :meth:`~Series.interpolate` diff --git a/doc/source/user_guide/missing_data.rst b/doc/source/user_guide/missing_data.rst index 6ea4c213e85c8..0a1059c67c67a 100644 --- a/doc/source/user_guide/missing_data.rst +++ b/doc/source/user_guide/missing_data.rst @@ -150,7 +150,7 @@ objects. :suppress: df = df2.loc[:, ["one", "two", "three"]] - a = df2.loc[df2.index[:5], ["one", "two"]].fillna(method="pad") + a = df2.loc[df2.index[:5], ["one", "two"]].ffill() b = df2.loc[df2.index[:5], ["one", "two", "three"]] .. ipython:: python @@ -242,7 +242,7 @@ can propagate non-NA values forward or backward: .. ipython:: python df - df.fillna(method="pad") + df.ffill() .. _missing_data.fillna.limit: @@ -259,7 +259,7 @@ we can use the ``limit`` keyword: .. ipython:: python df - df.fillna(method="pad", limit=1) + df.ffill(limit=1) To remind you, these are the available filling methods: diff --git a/doc/source/whatsnew/v0.10.0.rst b/doc/source/whatsnew/v0.10.0.rst index 388e716d122a5..c7802749e1d75 100644 --- a/doc/source/whatsnew/v0.10.0.rst +++ b/doc/source/whatsnew/v0.10.0.rst @@ -226,6 +226,7 @@ labeled the aggregated group with the end of the interval: the next day). valid code. You must either specify a fill value or an interpolation method: .. ipython:: python + :okwarning: s = pd.Series([np.nan, 1.0, 2.0, np.nan, 4]) s diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index 7cc2e19f477dd..93f2c451a5663 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -271,6 +271,7 @@ Deprecations - Deprecated behavior of :func:`assert_series_equal` and :func:`assert_frame_equal` considering NA-like values (e.g. ``NaN`` vs ``None`` as equivalent) (:issue:`52081`) - Deprecated constructing :class:`SparseArray` from scalar data, pass a sequence instead (:issue:`53039`) - 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`) +- 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`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/generic.py b/pandas/core/generic.py index bcfbfa1a2b713..d544572763404 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6793,6 +6793,60 @@ def convert_dtypes( # ---------------------------------------------------------------------- # Filling NA's + def _deprecate_downcast(self, downcast) -> None: + if isinstance(downcast, dict): + # GH#40988 + for dc in downcast.values(): + if dc is not None and dc is not False and dc != "infer": + warnings.warn( + "downcast entries other than None, False, and 'infer' " + "are deprecated and will raise in a future version", + FutureWarning, + stacklevel=find_stack_level(), + ) + elif downcast is not None and downcast is not False and downcast != "infer": + # GH#40988 + warnings.warn( + "downcast other than None, False, and 'infer' are deprecated " + "and will raise in a future version", + FutureWarning, + stacklevel=find_stack_level(), + ) + + @final + def _fillna_with_method( + self, + method: Literal["ffill", "bfill"], + *, + axis: None | Axis = None, + inplace: bool_t = False, + limit: None | int = None, + downcast: dict | None = None, + ): + if axis is None: + axis = 0 + axis = self._get_axis_number(axis) + + if not self._mgr.is_single_block and axis == 1: + if inplace: + raise NotImplementedError() + result = self.T._fillna_with_method(method=method, limit=limit).T + + return result + + new_mgr = self._mgr.interpolate( + method=method, + axis=axis, + limit=limit, + inplace=inplace, + downcast=downcast, + ) + result = self._constructor(new_mgr) + if inplace: + return self._update_inplace(result) + else: + return result.__finalize__(self, method="fillna") + @overload def fillna( self, @@ -6864,6 +6918,9 @@ def fillna( * ffill: propagate last valid observation forward to next valid. * backfill / bfill: use next valid observation to fill gap. + .. deprecated:: 2.1.0 + Use ffill or bfill instead. + axis : {axes_single_arg} Axis along which to fill missing values. For `Series` this parameter is unused and defaults to 0. @@ -6917,15 +6974,6 @@ def fillna( 2 0.0 0.0 0.0 0.0 3 0.0 3.0 0.0 4.0 - We can also propagate non-null values forward or backward. - - >>> df.fillna(method="ffill") - A B C D - 0 NaN 2.0 NaN 0.0 - 1 3.0 4.0 NaN 1.0 - 2 3.0 4.0 NaN 1.0 - 3 3.0 3.0 NaN 4.0 - Replace all NaN elements in column 'A', 'B', 'C', and 'D', with 0, 1, 2, and 3 respectively. @@ -6961,26 +7009,17 @@ def fillna( """ inplace = validate_bool_kwarg(inplace, "inplace") value, method = validate_fillna_kwargs(value, method) - - if isinstance(downcast, dict): - # GH#40988 - for dc in downcast.values(): - if dc is not None and dc is not False and dc != "infer": - warnings.warn( - "downcast entries other than None, False, and 'infer' " - "are deprecated and will raise in a future version", - FutureWarning, - stacklevel=find_stack_level(), - ) - elif downcast is not None and downcast is not False and downcast != "infer": - # GH#40988 + if method is not None: warnings.warn( - "downcast other than None, False, and 'infer' are deprecated " - "and will raise in a future version", + f"{type(self).__name__}.fillna with 'method' is deprecated and " + "will raise in a future version. Use obj.ffill() or obj.bfill() " + "instead.", FutureWarning, stacklevel=find_stack_level(), ) + self._deprecate_downcast(downcast) + # set the default here, so functions examining the signaure # can detect if something was set (e.g. in groupby) (GH9221) if axis is None: @@ -6988,19 +7027,8 @@ def fillna( axis = self._get_axis_number(axis) if value is None: - if not self._mgr.is_single_block and axis == 1: - if inplace: - raise NotImplementedError() - result = self.T.fillna(method=method, limit=limit).T - - return result - - new_data = self._mgr.interpolate( - method=method, - axis=axis, - limit=limit, - inplace=inplace, - downcast=downcast, + return self._fillna_with_method( + method, axis=axis, limit=limit, inplace=inplace, downcast=downcast ) else: if self.ndim == 1: @@ -7167,9 +7195,33 @@ def ffill( ------- {klass} or None Object with missing values filled or None if ``inplace=True``. + + Examples + -------- + >>> df = pd.DataFrame([[np.nan, 2, np.nan, 0], + ... [3, 4, np.nan, 1], + ... [np.nan, np.nan, np.nan, np.nan], + ... [np.nan, 3, np.nan, 4]], + ... columns=list("ABCD")) + >>> df + A B C D + 0 NaN 2.0 NaN 0.0 + 1 3.0 4.0 NaN 1.0 + 2 NaN NaN NaN NaN + 3 NaN 3.0 NaN 4.0 + + >>> df.ffill() + A B C D + 0 NaN 2.0 NaN 0.0 + 1 3.0 4.0 NaN 1.0 + 2 3.0 4.0 NaN 1.0 + 3 3.0 3.0 NaN 4.0 + """ - return self.fillna( - method="ffill", axis=axis, inplace=inplace, limit=limit, downcast=downcast + self._deprecate_downcast(downcast) + + return self._fillna_with_method( + "ffill", axis=axis, inplace=inplace, limit=limit, downcast=downcast ) @final @@ -7299,8 +7351,9 @@ def bfill( 2 4.0 7 3 4.0 7 """ - return self.fillna( - method="bfill", axis=axis, inplace=inplace, limit=limit, downcast=downcast + self._deprecate_downcast(downcast) + return self._fillna_with_method( + "bfill", axis=axis, inplace=inplace, limit=limit, downcast=downcast ) @final @@ -9814,8 +9867,8 @@ def _align_frame( ) if method is not None: - left = left.fillna(method=method, axis=fill_axis, limit=limit) - right = right.fillna(method=method, axis=fill_axis, limit=limit) + left = left._fillna_with_method(method, axis=fill_axis, limit=limit) + right = right._fillna_with_method(method, axis=fill_axis, limit=limit) return left, right, join_index @@ -9890,8 +9943,13 @@ def _align_series( # fill fill_na = notna(fill_value) or (method is not None) if fill_na: - left = left.fillna(fill_value, method=method, limit=limit, axis=fill_axis) - right = right.fillna(fill_value, method=method, limit=limit) + fill_value, method = validate_fillna_kwargs(fill_value, method) + if method is not None: + left = left._fillna_with_method(method, limit=limit, axis=fill_axis) + right = right._fillna_with_method(method, limit=limit) + else: + left = left.fillna(fill_value, limit=limit, axis=fill_axis) + right = right.fillna(fill_value, limit=limit) return left, right, join_index @@ -11257,9 +11315,7 @@ def pct_change( if fill_method is None: data = self else: - _data = self.fillna(method=fill_method, axis=axis, limit=limit) - assert _data is not None # needed for mypy - data = _data + data = self._fillna_with_method(fill_method, axis=axis, limit=limit) shifted = data.shift(periods=periods, freq=freq, axis=axis, **kwargs) # Unsupported left operand type for / ("Self") diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 37ef04f17a2e5..f764e6e1bc700 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -851,6 +851,10 @@ def fillna( Method to use for filling holes. ``'ffill'`` will propagate the last valid observation forward within a group. ``'bfill'`` will use next valid observation to fill the gap. + + .. deprecated:: 2.1.0 + Use obj.ffill or obj.bfill instead. + axis : {0 or 'index', 1 or 'columns'} Unused, only for compatibility with :meth:`DataFrameGroupBy.fillna`. @@ -881,49 +885,6 @@ def fillna( -------- ffill : Forward fill values within a group. bfill : Backward fill values within a group. - - Examples - -------- - >>> ser = pd.Series([np.nan, np.nan, 2, 3, np.nan, np.nan]) - >>> ser - 0 NaN - 1 NaN - 2 2.0 - 3 3.0 - 4 NaN - 5 NaN - dtype: float64 - - Propagate non-null values forward or backward within each group. - - >>> ser.groupby([0, 0, 0, 1, 1, 1]).fillna(method="ffill") - 0 NaN - 1 NaN - 2 2.0 - 3 3.0 - 4 3.0 - 5 3.0 - dtype: float64 - - >>> ser.groupby([0, 0, 0, 1, 1, 1]).fillna(method="bfill") - 0 2.0 - 1 2.0 - 2 2.0 - 3 3.0 - 4 NaN - 5 NaN - dtype: float64 - - Only replace the first NaN element within a group. - - >>> ser.groupby([0, 0, 0, 1, 1, 1]).fillna(method="ffill", limit=1) - 0 NaN - 1 NaN - 2 2.0 - 3 3.0 - 4 3.0 - 5 NaN - dtype: float64 """ result = self._op_via_apply( "fillna", @@ -2473,6 +2434,15 @@ def fillna( 3 3.0 NaN 2.0 4 3.0 NaN NaN """ + if method is not None: + warnings.warn( + f"{type(self).__name__}.fillna with 'method' is deprecated and " + "will raise in a future version. Use obj.ffill() or obj.bfill() " + "instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) + result = self._op_via_apply( "fillna", value=value, diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index bdab641719ded..68b541c5a6d64 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -2994,6 +2994,54 @@ def ffill(self, limit: int | None = None): DataFrame.ffill: Object with missing values filled or None if inplace=True. Series.fillna: Fill NaN values of a Series. DataFrame.fillna: Fill NaN values of a DataFrame. + + Examples + -------- + >>> df = pd.DataFrame( + ... { + ... "key": [0, 0, 1, 1, 1], + ... "A": [np.nan, 2, np.nan, 3, np.nan], + ... "B": [2, 3, np.nan, np.nan, np.nan], + ... "C": [np.nan, np.nan, 2, np.nan, np.nan], + ... } + ... ) + >>> df + key A B C + 0 0 NaN 2.0 NaN + 1 0 2.0 3.0 NaN + 2 1 NaN NaN 2.0 + 3 1 3.0 NaN NaN + 4 1 NaN NaN NaN + + Propagate non-null values forward or backward within each group along columns. + + >>> df.groupby("key").ffill() + A B C + 0 NaN 2.0 NaN + 1 2.0 3.0 NaN + 2 NaN NaN 2.0 + 3 3.0 NaN 2.0 + 4 3.0 NaN 2.0 + + Propagate non-null values forward or backward within each group along rows. + + >>> df.T.groupby(np.array([0, 0, 1, 1])).ffill().T + key A B C + 0 0.0 0.0 2.0 2.0 + 1 0.0 2.0 3.0 3.0 + 2 1.0 1.0 NaN 2.0 + 3 1.0 3.0 NaN NaN + 4 1.0 1.0 NaN NaN + + Only replace the first NaN element within a group along rows. + + >>> df.groupby("key").ffill(limit=1) + A B C + 0 NaN 2.0 NaN + 1 2.0 3.0 NaN + 2 NaN NaN 2.0 + 3 3.0 NaN 2.0 + 4 3.0 NaN NaN """ return self._fill("ffill", limit=limit) diff --git a/pandas/core/resample.py b/pandas/core/resample.py index f8adb2332609b..0086947db97dc 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -823,6 +823,14 @@ def fillna(self, method, limit: int | None = None): 2018-01-01 01:30:00 6.0 5 2018-01-01 02:00:00 6.0 5 """ + if method is not None: + warnings.warn( + f"{type(self).__name__}.fillna with 'method' is deprecated and " + "will raise in a future version. Use obj.ffill() or obj.bfill() " + "instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) return self._upsample(method, limit=limit) def interpolate( diff --git a/pandas/tests/arrays/test_datetimes.py b/pandas/tests/arrays/test_datetimes.py index b8cd8a5546f05..2acc7bdc0d902 100644 --- a/pandas/tests/arrays/test_datetimes.py +++ b/pandas/tests/arrays/test_datetimes.py @@ -537,11 +537,11 @@ def test_fillna_2d(self): # test the DataFrame method while we're here df = pd.DataFrame(dta) - res = df.fillna(method="pad") + res = df.ffill() expected = pd.DataFrame(expected1) tm.assert_frame_equal(res, expected) - res = df.fillna(method="backfill") + res = df.bfill() expected = pd.DataFrame(expected2) tm.assert_frame_equal(res, expected) diff --git a/pandas/tests/extension/base/missing.py b/pandas/tests/extension/base/missing.py index 8a53c06e0b7bf..81ca829c8db0d 100644 --- a/pandas/tests/extension/base/missing.py +++ b/pandas/tests/extension/base/missing.py @@ -69,12 +69,18 @@ def test_fillna_scalar(self, data_missing): expected = data_missing.fillna(valid) self.assert_extension_array_equal(result, expected) + @pytest.mark.filterwarnings( + "ignore:Series.fillna with 'method' is deprecated:FutureWarning" + ) def test_fillna_limit_pad(self, data_missing): arr = data_missing.take([1, 0, 0, 0, 1]) - result = pd.Series(arr).fillna(method="ffill", limit=2) + result = pd.Series(arr).ffill(limit=2) expected = pd.Series(data_missing.take([1, 1, 1, 0, 1])) self.assert_series_equal(result, expected) + @pytest.mark.filterwarnings( + "ignore:Series.fillna with 'method' is deprecated:FutureWarning" + ) def test_fillna_limit_backfill(self, data_missing): arr = data_missing.take([1, 0, 0, 0, 1]) result = pd.Series(arr).fillna(method="backfill", limit=2) @@ -119,7 +125,7 @@ def test_fillna_series_method(self, data_missing, fillna_method): if fillna_method == "ffill": data_missing = data_missing[::-1] - result = pd.Series(data_missing).fillna(method=fillna_method) + result = getattr(pd.Series(data_missing), fillna_method)() expected = pd.Series( data_missing._from_sequence( [fill_value, fill_value], dtype=data_missing.dtype diff --git a/pandas/tests/extension/test_sparse.py b/pandas/tests/extension/test_sparse.py index f1514f83202c5..d8bab71b76df4 100644 --- a/pandas/tests/extension/test_sparse.py +++ b/pandas/tests/extension/test_sparse.py @@ -224,11 +224,13 @@ def test_isna(self, data_missing): self.assert_equal(sarr.isna(), expected) def test_fillna_limit_pad(self, data_missing): - with tm.assert_produces_warning(PerformanceWarning, check_stacklevel=False): + warns = (PerformanceWarning, FutureWarning) + with tm.assert_produces_warning(warns, check_stacklevel=False): super().test_fillna_limit_pad(data_missing) def test_fillna_limit_backfill(self, data_missing): - with tm.assert_produces_warning(PerformanceWarning, check_stacklevel=False): + warns = (PerformanceWarning, FutureWarning) + with tm.assert_produces_warning(warns, check_stacklevel=False): super().test_fillna_limit_backfill(data_missing) def test_fillna_no_op_returns_copy(self, data, request): @@ -239,9 +241,9 @@ def test_fillna_no_op_returns_copy(self, data, request): with tm.assert_produces_warning(PerformanceWarning, check_stacklevel=False): super().test_fillna_no_op_returns_copy(data) - def test_fillna_series_method(self, data_missing): + def test_fillna_series_method(self, data_missing, fillna_method): with tm.assert_produces_warning(PerformanceWarning, check_stacklevel=False): - super().test_fillna_limit_backfill(data_missing) + super().test_fillna_series_method(data_missing, fillna_method) @pytest.mark.xfail(reason="Unsupported") def test_fillna_series(self): diff --git a/pandas/tests/frame/methods/test_align.py b/pandas/tests/frame/methods/test_align.py index f968787eb5c4d..1dabc95a0f6f4 100644 --- a/pandas/tests/frame/methods/test_align.py +++ b/pandas/tests/frame/methods/test_align.py @@ -408,8 +408,10 @@ def _check_align(self, a, b, axis, fill_axis, how, method, limit=None): ea = ea.reindex(columns=join_columns) eb = eb.reindex(columns=join_columns) - ea = ea.fillna(axis=fill_axis, method=method, limit=limit) - eb = eb.fillna(axis=fill_axis, method=method, limit=limit) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + ea = ea.fillna(axis=fill_axis, method=method, limit=limit) + eb = eb.fillna(axis=fill_axis, method=method, limit=limit) tm.assert_frame_equal(aa, ea) tm.assert_frame_equal(ab, eb) diff --git a/pandas/tests/frame/methods/test_fillna.py b/pandas/tests/frame/methods/test_fillna.py index ded2c7702f6f5..d340e048994a9 100644 --- a/pandas/tests/frame/methods/test_fillna.py +++ b/pandas/tests/frame/methods/test_fillna.py @@ -68,7 +68,9 @@ def test_fillna_datetime(self, datetime_frame): zero_filled = datetime_frame.fillna(0) assert (zero_filled.loc[zero_filled.index[:5], "A"] == 0).all() - padded = datetime_frame.fillna(method="pad") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + padded = datetime_frame.fillna(method="pad") assert np.isnan(padded.loc[padded.index[:5], "A"]).all() assert ( padded.loc[padded.index[-5:], "A"] == padded.loc[padded.index[-5], "A"] @@ -87,7 +89,9 @@ def test_fillna_mixed_type(self, float_string_frame): mf.loc[mf.index[-10:], "A"] = np.nan # TODO: make stronger assertion here, GH 25640 mf.fillna(value=0) - mf.fillna(method="pad") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + mf.fillna(method="pad") def test_fillna_mixed_float(self, mixed_float_frame): # mixed numeric (but no float16) @@ -96,15 +100,19 @@ def test_fillna_mixed_float(self, mixed_float_frame): result = mf.fillna(value=0) _check_mixed_float(result, dtype={"C": None}) - result = mf.fillna(method="pad") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = mf.fillna(method="pad") _check_mixed_float(result, dtype={"C": None}) def test_fillna_empty(self): # empty frame (GH#2778) df = DataFrame(columns=["x"]) for m in ["pad", "backfill"]: - df.x.fillna(method=m, inplace=True) - df.x.fillna(method=m) + msg = "Series.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + df.x.fillna(method=m, inplace=True) + df.x.fillna(method=m) def test_fillna_different_dtype(self): # with different dtype (GH#3386) @@ -161,7 +169,10 @@ def test_fillna_tzaware(self): ] } ) - tm.assert_frame_equal(df.fillna(method="pad"), exp) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = df.fillna(method="pad") + tm.assert_frame_equal(res, exp) df = DataFrame({"A": [NaT, Timestamp("2012-11-11 00:00:00+01:00")]}) exp = DataFrame( @@ -172,7 +183,10 @@ def test_fillna_tzaware(self): ] } ) - tm.assert_frame_equal(df.fillna(method="bfill"), exp) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = df.fillna(method="bfill") + tm.assert_frame_equal(res, exp) def test_fillna_tzaware_different_column(self): # with timezone in another column @@ -183,7 +197,9 @@ def test_fillna_tzaware_different_column(self): "B": [1, 2, np.nan, np.nan], } ) - result = df.fillna(method="pad") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.fillna(method="pad") expected = DataFrame( { "A": date_range("20130101", periods=4, tz="US/Eastern"), @@ -214,7 +230,9 @@ def test_na_actions_categorical(self): with pytest.raises(TypeError, match=msg): df.fillna(value={"cats": 4, "vals": "c"}) - res = df.fillna(method="pad") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = df.fillna(method="pad") tm.assert_frame_equal(res, df_exp_fill) # dropna @@ -398,17 +416,20 @@ def test_ffill(self, datetime_frame): datetime_frame.loc[datetime_frame.index[:5], "A"] = np.nan datetime_frame.loc[datetime_frame.index[-5:], "A"] = np.nan - tm.assert_frame_equal( - datetime_frame.ffill(), datetime_frame.fillna(method="ffill") - ) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + alt = datetime_frame.fillna(method="ffill") + tm.assert_frame_equal(datetime_frame.ffill(), alt) def test_bfill(self, datetime_frame): datetime_frame.loc[datetime_frame.index[:5], "A"] = np.nan datetime_frame.loc[datetime_frame.index[-5:], "A"] = np.nan - tm.assert_frame_equal( - datetime_frame.bfill(), datetime_frame.fillna(method="bfill") - ) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + alt = datetime_frame.fillna(method="bfill") + + tm.assert_frame_equal(datetime_frame.bfill(), alt) def test_frame_pad_backfill_limit(self): index = np.arange(10) @@ -416,13 +437,16 @@ def test_frame_pad_backfill_limit(self): result = df[:2].reindex(index, method="pad", limit=5) - expected = df[:2].reindex(index).fillna(method="pad") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df[:2].reindex(index).fillna(method="pad") expected.iloc[-3:] = np.nan tm.assert_frame_equal(result, expected) result = df[-2:].reindex(index, method="backfill", limit=5) - expected = df[-2:].reindex(index).fillna(method="backfill") + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df[-2:].reindex(index).fillna(method="backfill") expected.iloc[:3] = np.nan tm.assert_frame_equal(result, expected) @@ -431,16 +455,21 @@ def test_frame_fillna_limit(self): df = DataFrame(np.random.randn(10, 4), index=index) result = df[:2].reindex(index) - result = result.fillna(method="pad", limit=5) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = result.fillna(method="pad", limit=5) - expected = df[:2].reindex(index).fillna(method="pad") + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df[:2].reindex(index).fillna(method="pad") expected.iloc[-3:] = np.nan tm.assert_frame_equal(result, expected) result = df[-2:].reindex(index) - result = result.fillna(method="backfill", limit=5) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = result.fillna(method="backfill", limit=5) - expected = df[-2:].reindex(index).fillna(method="backfill") + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df[-2:].reindex(index).fillna(method="backfill") expected.iloc[:3] = np.nan tm.assert_frame_equal(result, expected) @@ -484,10 +513,13 @@ def test_fillna_inplace(self): df.loc[:4, 1] = np.nan df.loc[-4:, 3] = np.nan - expected = df.fillna(method="ffill") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df.fillna(method="ffill") assert expected is not df - df.fillna(method="ffill", inplace=True) + with tm.assert_produces_warning(FutureWarning, match=msg): + df.fillna(method="ffill", inplace=True) tm.assert_frame_equal(df, expected) def test_fillna_dict_series(self): @@ -558,13 +590,18 @@ def test_fillna_columns(self): arr[:, ::2] = np.nan df = DataFrame(arr) - result = df.fillna(method="ffill", axis=1) - expected = df.T.fillna(method="pad").T + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.fillna(method="ffill", axis=1) + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df.T.fillna(method="pad").T tm.assert_frame_equal(result, expected) df.insert(6, "foo", 5) - result = df.fillna(method="ffill", axis=1) - expected = df.astype(float).fillna(method="ffill", axis=1) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.fillna(method="ffill", axis=1) + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df.astype(float).fillna(method="ffill", axis=1) tm.assert_frame_equal(result, expected) def test_fillna_invalid_method(self, float_frame): @@ -591,7 +628,9 @@ def test_fillna_col_reordering(self): cols = ["COL." + str(i) for i in range(5, 0, -1)] data = np.random.rand(20, 5) df = DataFrame(index=range(20), columns=cols, data=data) - filled = df.fillna(method="ffill") + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + filled = df.fillna(method="ffill") assert df.columns.tolist() == filled.columns.tolist() def test_fill_corner(self, float_frame, float_string_frame): diff --git a/pandas/tests/frame/methods/test_interpolate.py b/pandas/tests/frame/methods/test_interpolate.py index 057561aa1d58b..9eb1073f4c69c 100644 --- a/pandas/tests/frame/methods/test_interpolate.py +++ b/pandas/tests/frame/methods/test_interpolate.py @@ -434,7 +434,8 @@ def test_interp_fillna_methods(self, request, axis, method, using_array_manager) "C": [3.0, 6.0, 9.0, np.nan, np.nan, 30.0], } ) - expected = df.fillna(axis=axis, method=method) + method2 = method if method != "pad" else "ffill" + expected = getattr(df, method2)(axis=axis) result = df.interpolate(method=method, axis=axis) tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/frame/methods/test_pct_change.py b/pandas/tests/frame/methods/test_pct_change.py index a9699f8d15146..37d6361dec935 100644 --- a/pandas/tests/frame/methods/test_pct_change.py +++ b/pandas/tests/frame/methods/test_pct_change.py @@ -51,15 +51,15 @@ def test_pct_change(self, datetime_frame): tm.assert_frame_equal(rs, datetime_frame / datetime_frame.shift(1) - 1) rs = datetime_frame.pct_change(2) - filled = datetime_frame.fillna(method="pad") + filled = datetime_frame.ffill() tm.assert_frame_equal(rs, filled / filled.shift(2) - 1) rs = datetime_frame.pct_change(fill_method="bfill", limit=1) - filled = datetime_frame.fillna(method="bfill", limit=1) + filled = datetime_frame.bfill(limit=1) tm.assert_frame_equal(rs, filled / filled.shift(1) - 1) rs = datetime_frame.pct_change(freq="5D") - filled = datetime_frame.fillna(method="pad") + filled = datetime_frame.ffill() tm.assert_frame_equal( rs, (filled / filled.shift(freq="5D") - 1).reindex_like(filled) ) diff --git a/pandas/tests/frame/methods/test_replace.py b/pandas/tests/frame/methods/test_replace.py index 1619b79f64514..d5668020bab5d 100644 --- a/pandas/tests/frame/methods/test_replace.py +++ b/pandas/tests/frame/methods/test_replace.py @@ -726,8 +726,11 @@ def test_replace_for_new_dtypes(self, datetime_frame): b = tsframe["B"] b[b == -1e8] = np.nan tsframe["B"] = b - result = tsframe.fillna(method="bfill") - tm.assert_frame_equal(result, tsframe.fillna(method="bfill")) + msg = "DataFrame.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + # TODO: what is this even testing? + result = tsframe.fillna(method="bfill") + tm.assert_frame_equal(result, tsframe.fillna(method="bfill")) @pytest.mark.parametrize( "frame, to_replace, value, expected", diff --git a/pandas/tests/generic/test_finalize.py b/pandas/tests/generic/test_finalize.py index 8159024966b0f..c3e25e193c77e 100644 --- a/pandas/tests/generic/test_finalize.py +++ b/pandas/tests/generic/test_finalize.py @@ -441,6 +441,9 @@ def ndframe_method(request): return request.param +@pytest.mark.filterwarnings( + "ignore:DataFrame.fillna with 'method' is deprecated:FutureWarning" +) def test_finalize_called(ndframe_method): cls, init_args, method = ndframe_method ndframe = cls(*init_args) diff --git a/pandas/tests/groupby/test_missing.py b/pandas/tests/groupby/test_missing.py index d2939573fb994..37bf22279b38c 100644 --- a/pandas/tests/groupby/test_missing.py +++ b/pandas/tests/groupby/test_missing.py @@ -50,7 +50,9 @@ def test_fillna_with_string_dtype(method, expected): # GH 40250 df = DataFrame({"a": pd.array([None, "a", None], dtype="string"), "b": [0, 0, 0]}) grp = df.groupby("b") - result = grp.fillna(method=method) + msg = "DataFrameGroupBy.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = grp.fillna(method=method) expected = DataFrame({"a": pd.array(expected, dtype="string")}) tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/groupby/transform/test_transform.py b/pandas/tests/groupby/transform/test_transform.py index 09b24284d3b37..eb7e6c154afc9 100644 --- a/pandas/tests/groupby/transform/test_transform.py +++ b/pandas/tests/groupby/transform/test_transform.py @@ -356,9 +356,13 @@ def test_dispatch_transform(tsframe): grouped = df.groupby(lambda x: x.month) - filled = grouped.fillna(method="pad") + msg = "DataFrameGroupBy.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + filled = grouped.fillna(method="pad") + msg = "Series.fillna with 'method' is deprecated" fillit = lambda x: x.fillna(method="pad") - expected = df.groupby(lambda x: x.month).transform(fillit) + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = df.groupby(lambda x: x.month).transform(fillit) tm.assert_frame_equal(filled, expected) diff --git a/pandas/tests/resample/test_resample_api.py b/pandas/tests/resample/test_resample_api.py index 793e31295b8c3..058f104993ced 100644 --- a/pandas/tests/resample/test_resample_api.py +++ b/pandas/tests/resample/test_resample_api.py @@ -290,19 +290,23 @@ def test_fillna(): r = ts.resample("s") expected = r.ffill() - result = r.fillna(method="ffill") + msg = "DatetimeIndexResampler.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = r.fillna(method="ffill") tm.assert_series_equal(result, expected) expected = r.bfill() - result = r.fillna(method="bfill") + with tm.assert_produces_warning(FutureWarning, match=msg): + result = r.fillna(method="bfill") tm.assert_series_equal(result, expected) - msg = ( + msg2 = ( r"Invalid fill method\. Expecting pad \(ffill\), backfill " r"\(bfill\) or nearest\. Got 0" ) - with pytest.raises(ValueError, match=msg): - r.fillna(0) + with pytest.raises(ValueError, match=msg2): + with tm.assert_produces_warning(FutureWarning, match=msg): + r.fillna(0) @pytest.mark.parametrize( diff --git a/pandas/tests/series/methods/test_align.py b/pandas/tests/series/methods/test_align.py index 04951e6f42e36..3edbe1b2f61f3 100644 --- a/pandas/tests/series/methods/test_align.py +++ b/pandas/tests/series/methods/test_align.py @@ -80,8 +80,10 @@ def test_align_fill_method( ea = a.reindex(join_index) eb = b.reindex(join_index) - ea = ea.fillna(method=method, limit=limit) - eb = eb.fillna(method=method, limit=limit) + msg2 = "Series.fillna with 'method' is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg2): + ea = ea.fillna(method=method, limit=limit) + eb = eb.fillna(method=method, limit=limit) tm.assert_series_equal(aa, ea) tm.assert_series_equal(ab, eb) diff --git a/pandas/tests/series/methods/test_fillna.py b/pandas/tests/series/methods/test_fillna.py index df9e218e9fae4..7665e4d015a45 100644 --- a/pandas/tests/series/methods/test_fillna.py +++ b/pandas/tests/series/methods/test_fillna.py @@ -24,6 +24,9 @@ from pandas.core.arrays import period_array +@pytest.mark.filterwarnings( + "ignore:(Series|DataFrame).fillna with 'method' is deprecated:FutureWarning" +) class TestSeriesFillNA: def test_fillna_nat(self): series = Series([0, 1, 2, NaT._value], dtype="M8[ns]") @@ -846,6 +849,9 @@ def test_fillna_categorical_accept_same_type( tm.assert_categorical_equal(result, expected) +@pytest.mark.filterwarnings( + "ignore:Series.fillna with 'method' is deprecated:FutureWarning" +) class TestFillnaPad: def test_fillna_bug(self): ser = Series([np.nan, 1.0, np.nan, 3.0, np.nan], ["z", "a", "b", "c", "d"]) @@ -934,7 +940,7 @@ def test_datetime64tz_fillna_round_issue(self): [NaT, NaT, datetime(2016, 12, 12, 22, 24, 6, 100001, tzinfo=pytz.utc)] ) - filled = data.fillna(method="bfill") + filled = data.bfill() expected = Series( [ @@ -965,7 +971,7 @@ def test_fillna_parr(self): ) expected = Series(arr) - filled = ser.fillna(method="pad") + filled = ser.ffill() tm.assert_series_equal(filled, expected) diff --git a/pandas/tests/series/methods/test_pct_change.py b/pandas/tests/series/methods/test_pct_change.py index 017fef5fdb31f..475d729b6ce78 100644 --- a/pandas/tests/series/methods/test_pct_change.py +++ b/pandas/tests/series/methods/test_pct_change.py @@ -14,15 +14,15 @@ def test_pct_change(self, datetime_series): tm.assert_series_equal(rs, datetime_series / datetime_series.shift(1) - 1) rs = datetime_series.pct_change(2) - filled = datetime_series.fillna(method="pad") + filled = datetime_series.ffill() tm.assert_series_equal(rs, filled / filled.shift(2) - 1) rs = datetime_series.pct_change(fill_method="bfill", limit=1) - filled = datetime_series.fillna(method="bfill", limit=1) + filled = datetime_series.bfill(limit=1) tm.assert_series_equal(rs, filled / filled.shift(1) - 1) rs = datetime_series.pct_change(freq="5D") - filled = datetime_series.fillna(method="pad") + filled = datetime_series.ffill() tm.assert_series_equal( rs, (filled / filled.shift(freq="5D") - 1).reindex_like(filled) ) diff --git a/pandas/tests/series/methods/test_reindex.py b/pandas/tests/series/methods/test_reindex.py index 04a15b4e95e0a..16fc04d588a52 100644 --- a/pandas/tests/series/methods/test_reindex.py +++ b/pandas/tests/series/methods/test_reindex.py @@ -156,7 +156,7 @@ def test_reindex_pad(): # GH4618 shifted series downcasting s = Series(False, index=range(0, 5)) - result = s.shift(1).fillna(method="bfill") + result = s.shift(1).bfill() expected = Series(False, index=range(0, 5)) tm.assert_series_equal(result, expected) diff --git a/pandas/tests/window/moments/test_moments_consistency_ewm.py b/pandas/tests/window/moments/test_moments_consistency_ewm.py index 1d58c64d55b15..49dee50954f4f 100644 --- a/pandas/tests/window/moments/test_moments_consistency_ewm.py +++ b/pandas/tests/window/moments/test_moments_consistency_ewm.py @@ -65,12 +65,7 @@ def test_ewm_consistency_mean(all_data, adjust, ignore_na, min_periods): com=com, min_periods=min_periods, adjust=adjust, ignore_na=ignore_na ).mean() weights = create_mock_weights(all_data, com=com, adjust=adjust, ignore_na=ignore_na) - expected = ( - all_data.multiply(weights) - .cumsum() - .divide(weights.cumsum()) - .fillna(method="ffill") - ) + expected = all_data.multiply(weights).cumsum().divide(weights.cumsum()).ffill() expected[ all_data.expanding().count() < (max(min_periods, 1) if min_periods else 1) ] = np.nan @@ -118,8 +113,8 @@ def test_ewm_consistency_var_debiasing_factors( ).var(bias=True) weights = create_mock_weights(all_data, com=com, adjust=adjust, ignore_na=ignore_na) - cum_sum = weights.cumsum().fillna(method="ffill") - cum_sum_sq = (weights * weights).cumsum().fillna(method="ffill") + cum_sum = weights.cumsum().ffill() + cum_sum_sq = (weights * weights).cumsum().ffill() numerator = cum_sum * cum_sum denominator = numerator - cum_sum_sq denominator[denominator <= 0.0] = np.nan diff --git a/pandas/tests/window/test_ewm.py b/pandas/tests/window/test_ewm.py index f4643be53f120..352828a155f6d 100644 --- a/pandas/tests/window/test_ewm.py +++ b/pandas/tests/window/test_ewm.py @@ -403,7 +403,7 @@ def test_ewma_nan_handling(): ) def test_ewma_nan_handling_cases(s, adjust, ignore_na, w): # GH 7603 - expected = (s.multiply(w).cumsum() / Series(w).cumsum()).fillna(method="ffill") + expected = (s.multiply(w).cumsum() / Series(w).cumsum()).ffill() result = s.ewm(com=2.0, adjust=adjust, ignore_na=ignore_na).mean() tm.assert_series_equal(result, expected) From ac216838b9d95488889c81d5fc19bf1d509e9553 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Jun 2023 10:47:17 -0700 Subject: [PATCH 2/7] deprecate Resampler.fillna entirely --- pandas/conftest.py | 4 ++++ pandas/core/resample.py | 15 +++++++-------- pandas/tests/resample/test_resample_api.py | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pandas/conftest.py b/pandas/conftest.py index 7dab1714e0aa3..bba0875da1c7a 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -150,6 +150,10 @@ def pytest_collection_modifyitems(items, config) -> None: "first is deprecated and will be removed in a future version. " "Please create a mask and filter using `.loc` instead", ), + ( + "DataFrameGroupBy.fillna", + "DataFrameGroupBy.fillna with 'method' is deprecated", + ), ] for item in items: diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 0086947db97dc..ad40571f09078 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -823,14 +823,13 @@ def fillna(self, method, limit: int | None = None): 2018-01-01 01:30:00 6.0 5 2018-01-01 02:00:00 6.0 5 """ - if method is not None: - warnings.warn( - f"{type(self).__name__}.fillna with 'method' is deprecated and " - "will raise in a future version. Use obj.ffill() or obj.bfill() " - "instead.", - FutureWarning, - stacklevel=find_stack_level(), - ) + warnings.warn( + f"{type(self).__name__}.fillna is deprecated and will be removed " + "in a future version. Use obj.ffill(), obj.bfill(), " + "or obj.neaerest() instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) return self._upsample(method, limit=limit) def interpolate( diff --git a/pandas/tests/resample/test_resample_api.py b/pandas/tests/resample/test_resample_api.py index 058f104993ced..d7b8f0c8053da 100644 --- a/pandas/tests/resample/test_resample_api.py +++ b/pandas/tests/resample/test_resample_api.py @@ -290,7 +290,7 @@ def test_fillna(): r = ts.resample("s") expected = r.ffill() - msg = "DatetimeIndexResampler.fillna with 'method' is deprecated" + msg = "DatetimeIndexResampler.fillna is deprecated" with tm.assert_produces_warning(FutureWarning, match=msg): result = r.fillna(method="ffill") tm.assert_series_equal(result, expected) From 029917262dda23b3ae142920e78f5a6043e190c1 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Jun 2023 12:43:32 -0700 Subject: [PATCH 3/7] suppress doctest warnings --- pandas/conftest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/conftest.py b/pandas/conftest.py index bba0875da1c7a..a6b1a8815d475 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -150,6 +150,10 @@ def pytest_collection_modifyitems(items, config) -> None: "first is deprecated and will be removed in a future version. " "Please create a mask and filter using `.loc` instead", ), + ( + "Resampler.fillna", + "DatetimeIndexResampler.fillna is deprecated", + ), ( "DataFrameGroupBy.fillna", "DataFrameGroupBy.fillna with 'method' is deprecated", From 6757a440606e84126c8013a8db19420251da2936 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Jun 2023 13:41:45 -0700 Subject: [PATCH 4/7] typo fixup --- pandas/core/resample.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/resample.py b/pandas/core/resample.py index ad40571f09078..8291162db0834 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -826,7 +826,7 @@ def fillna(self, method, limit: int | None = None): warnings.warn( f"{type(self).__name__}.fillna is deprecated and will be removed " "in a future version. Use obj.ffill(), obj.bfill(), " - "or obj.neaerest() instead.", + "or obj.nearest() instead.", FutureWarning, stacklevel=find_stack_level(), ) From a2cbe9f796db43f455fec18cc02dd279a1615d80 Mon Sep 17 00:00:00 2001 From: Brock Date: Mon, 5 Jun 2023 15:46:43 -0700 Subject: [PATCH 5/7] doctest --- pandas/conftest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/conftest.py b/pandas/conftest.py index a6b1a8815d475..fbef2fb272ed6 100644 --- a/pandas/conftest.py +++ b/pandas/conftest.py @@ -158,6 +158,10 @@ def pytest_collection_modifyitems(items, config) -> None: "DataFrameGroupBy.fillna", "DataFrameGroupBy.fillna with 'method' is deprecated", ), + ( + "DataFrameGroupBy.fillna", + "DataFrame.fillna with 'method' is deprecated", + ), ] for item in items: From 05de642add693e73152531050cb892b6ddc95173 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 6 Jun 2023 11:04:11 -0700 Subject: [PATCH 6/7] mypy fixup --- pandas/core/generic.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 90bfd8bc07d93..11ea736d3c395 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6823,7 +6823,7 @@ def _deprecate_downcast(self, downcast) -> None: @final def _fillna_with_method( self, - method: Literal["ffill", "bfill"], + method: Literal["ffill", "bfill", "pad", "backfill"], *, axis: None | Axis = None, inplace: bool_t = False, @@ -6833,6 +6833,7 @@ def _fillna_with_method( if axis is None: axis = 0 axis = self._get_axis_number(axis) + method = clean_fill_method(method) if not self._mgr.is_single_block and axis == 1: if inplace: @@ -7035,7 +7036,14 @@ def fillna( if value is None: return self._fillna_with_method( - method, axis=axis, limit=limit, inplace=inplace, downcast=downcast + # error: Argument 1 to "_fillna_with_method" of "NDFrame" has + # incompatible type "Optional[Literal['backfill', 'bfill', 'ffill', + # 'pad']]"; expected "Literal['ffill', 'bfill', 'pad', 'backfill']" + method, # type: ignore[arg-type] + axis=axis, + limit=limit, + inplace=inplace, + downcast=downcast, ) else: if self.ndim == 1: @@ -7136,7 +7144,10 @@ def fillna( if axis == 1: result = self.T.fillna(value=value, limit=limit).T - new_data = result + # error: Incompatible types in assignment (expression + # has type "Self", variable has type "Union[ArrayManager, + # SingleArrayManager, BlockManager, SingleBlockManager]") + new_data = result # type: ignore[assignment] else: new_data = self._mgr.fillna( value=value, limit=limit, inplace=inplace, downcast=downcast From 964a829da69df9ab3c628c9b69492cfb645db69f Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 7 Jun 2023 09:22:15 -0700 Subject: [PATCH 7/7] lint fixup --- ci/code_checks.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index 304b4616355db..61c68e0dd5e66 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -289,6 +289,7 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then pandas.core.groupby.SeriesGroupBy.cumprod \ pandas.core.groupby.SeriesGroupBy.cumsum \ pandas.core.groupby.SeriesGroupBy.diff \ + pandas.core.groupby.SeriesGroupBy.fillna \ pandas.core.groupby.SeriesGroupBy.ffill \ pandas.core.groupby.SeriesGroupBy.max \ pandas.core.groupby.SeriesGroupBy.median \