From 95490c909b3e0e41896d9b7f0f26d894eb74bde1 Mon Sep 17 00:00:00 2001 From: Richard Shadrach Date: Mon, 29 May 2023 10:39:13 -0400 Subject: [PATCH] DEPR: inplace in GroupBy.fillna --- doc/source/whatsnew/v2.1.0.rst | 2 +- pandas/core/groupby/generic.py | 34 ++++++++++++++++++++++++-- pandas/tests/groupby/test_function.py | 35 +++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index 2c5263f447951..59613df83dfae 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -269,7 +269,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 ``inplace`` argument of :class:`SeriesGroupBy.fillna` and :class:`DataFrameGroupBy.fillna`; setting ``inplace=True`` is currently broken (:issue:`48792`) .. --------------------------------------------------------------------------- .. _whatsnew_210.performance: diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 37ef04f17a2e5..ec4ccfc7bc6e1 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -830,7 +830,7 @@ def fillna( value: object | ArrayLike | None = None, method: FillnaOptions | None = None, axis: Axis | None | lib.NoDefault = lib.no_default, - inplace: bool = False, + inplace: bool | lib.NoDefault = lib.no_default, limit: int | None = None, downcast: dict | None = None, ) -> Series | None: @@ -860,6 +860,10 @@ def fillna( inplace : bool, default False Broken. Do not set to True. + + .. deprecated:: 2.1.0 + The inplace argument will be removed in a future version of pandas. + limit : int, default None If method is specified, this is the maximum number of consecutive NaN values to forward/backward fill within a group. In other words, @@ -925,6 +929,17 @@ def fillna( 5 NaN dtype: float64 """ + if inplace is not lib.no_default: + warnings.warn( + message=( + "Setting inplace=True is currently broken. The inplace argument " + "is deprecated and will be removed in a future version of pandas." + ), + category=FutureWarning, + stacklevel=find_stack_level(), + ) + else: + inplace = False result = self._op_via_apply( "fillna", value=value, @@ -2353,7 +2368,7 @@ def fillna( value: Hashable | Mapping | Series | DataFrame = None, method: FillnaOptions | None = None, axis: Axis | None | lib.NoDefault = lib.no_default, - inplace: bool = False, + inplace: bool | lib.NoDefault = lib.no_default, limit: int | None = None, downcast=None, ) -> DataFrame | None: @@ -2387,6 +2402,10 @@ def fillna( inplace : bool, default False Broken. Do not set to True. + + .. deprecated:: 2.1.0 + The inplace argument will be removed in a future version of pandas. + limit : int, default None If method is specified, this is the maximum number of consecutive NaN values to forward/backward fill within a group. In other words, @@ -2473,6 +2492,17 @@ def fillna( 3 3.0 NaN 2.0 4 3.0 NaN NaN """ + if inplace is not lib.no_default: + warnings.warn( + message=( + "Setting inplace=True is currently broken. The inplace argument " + "is deprecated and will be removed in a future version of pandas." + ), + category=FutureWarning, + stacklevel=find_stack_level(), + ) + else: + inplace = False result = self._op_via_apply( "fillna", value=value, diff --git a/pandas/tests/groupby/test_function.py b/pandas/tests/groupby/test_function.py index 98fce9d668e44..48ec10d6d32e1 100644 --- a/pandas/tests/groupby/test_function.py +++ b/pandas/tests/groupby/test_function.py @@ -1719,3 +1719,38 @@ def test_regression_allowlist_methods(op, axis, skipna, sort): if sort: expected = expected.sort_index(axis=axis) tm.assert_frame_equal(result, expected) + + +@pytest.mark.parametrize("inplace", [True, False, lib.no_default]) +def test_fillna_inplace_depr_frame(inplace): + # GH#48792 + df = DataFrame({"a": [1, 1, 2], "b": [3, 4, 5]}) + gb = df.groupby("a") + if inplace is lib.no_default: + result = gb.fillna(method="ffill", inplace=inplace) + else: + with tm.assert_produces_warning( + FutureWarning, match="The inplace argument is deprecated" + ): + result = gb.fillna(method="ffill", inplace=inplace) + expected = DataFrame() if inplace and inplace is not lib.no_default else df[["b"]] + tm.assert_frame_equal(result, expected) + + +@pytest.mark.parametrize("inplace", [True, False, lib.no_default]) +def test_fillna_inplace_depr_series(inplace): + # GH#48792 + ser = Series([3, 4, 5]) + gb = ser.groupby([1, 1, 2]) + if inplace is lib.no_default: + result = gb.fillna(method="ffill", inplace=inplace) + else: + with tm.assert_produces_warning( + FutureWarning, match="The inplace argument is deprecated" + ): + result = gb.fillna(method="ffill", inplace=inplace) + if inplace and inplace is not lib.no_default: + expected = Series([None, None], dtype=object, index=[1, 2]) + else: + expected = ser + tm.assert_series_equal(result, expected)