diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index 517baa648d805..970db240a453a 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -255,6 +255,7 @@ Deprecations - Deprecated making the functions in a list of functions given to :meth:`DataFrame.agg` attempt to operate on each element in the :class:`DataFrame` and only operate on the columns of the :class:`DataFrame` if the elementwise operations failed. To keep the current behavior, use :meth:`DataFrame.transform` instead. (:issue:`53325`) - Deprecated passing a :class:`DataFrame` to :meth:`DataFrame.from_records`, use :meth:`DataFrame.set_index` or :meth:`DataFrame.drop` instead (:issue:`51353`) - Deprecated silently dropping unrecognized timezones when parsing strings to datetimes (:issue:`18702`) +- Deprecated the "downcast" keyword in :meth:`Series.interpolate`, :meth:`DataFrame.interpolate`, :meth:`Series.fillna`, :meth:`DataFrame.fillna`, :meth:`Series.ffill`, :meth:`DataFrame.ffill`, :meth:`Series.bfill`, :meth:`DataFrame.bfill` (:issue:`40988`) - Deprecated the ``axis`` keyword in :meth:`DataFrame.ewm`, :meth:`Series.ewm`, :meth:`DataFrame.rolling`, :meth:`Series.rolling`, :meth:`DataFrame.expanding`, :meth:`Series.expanding` (:issue:`51778`) - Deprecated the ``axis`` keyword in :meth:`DataFrame.resample`, :meth:`Series.resample` (:issue:`51778`) - Deprecated the behavior of :func:`concat` with both ``len(keys) != len(objs)``, in a future version this will raise instead of truncating to the shorter of the two sequences (:issue:`43485`) @@ -292,7 +293,6 @@ Deprecations - Deprecated :meth:`Series.first` and :meth:`DataFrame.first` (please create a mask and filter using ``.loc`` instead) (:issue:`45908`) - Deprecated :meth:`Series.interpolate` and :meth:`DataFrame.interpolate` for object-dtype (:issue:`53631`) - Deprecated :meth:`Series.last` and :meth:`DataFrame.last` (please create a mask and filter using ``.loc`` instead) (:issue:`53692`) -- Deprecated allowing ``downcast`` keyword other than ``None``, ``False``, "infer", or a dict with these as values in :meth:`Series.fillna`, :meth:`DataFrame.fillna` (:issue:`40988`) - Deprecated allowing arbitrary ``fill_value`` in :class:`SparseDtype`, in a future version the ``fill_value`` will need to be compatible with the ``dtype.subtype``, either a scalar that can be held by that subtype or ``NaN`` for integer or bool subtypes (:issue:`23124`) - 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 bytes input to :func:`read_excel`. To read a file path, use a string or path-like object. (:issue:`53767`) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index a4b4466e8d609..94853cf50eb55 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6870,25 +6870,21 @@ 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 + def _deprecate_downcast(self, downcast, method_name: str): + # GH#40988 + if downcast is not lib.no_default: warnings.warn( - "downcast other than None, False, and 'infer' are deprecated " - "and will raise in a future version", + f"The 'downcast' keyword in {method_name} is deprecated and " + "will be removed in a future version. Use " + "res.infer_objects(copy=False) to infer non-object dtype, or " + "pd.to_numeric with the 'downcast' keyword to downcast numeric " + "results.", FutureWarning, stacklevel=find_stack_level(), ) + else: + downcast = None + return downcast @final def _pad_or_backfill( @@ -6977,7 +6973,7 @@ def fillna( axis: Axis | None = None, inplace: bool_t = False, limit: int | None = None, - downcast: dict | None = None, + downcast: dict | None | lib.NoDefault = lib.no_default, ) -> Self | None: """ Fill NA/NaN values using the specified method. @@ -7096,7 +7092,8 @@ def fillna( stacklevel=find_stack_level(), ) - self._deprecate_downcast(downcast) + was_no_default = downcast is lib.no_default + downcast = self._deprecate_downcast(downcast, "fillna") # set the default here, so functions examining the signaure # can detect if something was set (e.g. in groupby) (GH9221) @@ -7113,7 +7110,11 @@ def fillna( axis=axis, limit=limit, inplace=inplace, - downcast=downcast, + # error: Argument "downcast" to "_fillna_with_method" of "NDFrame" + # has incompatible type "Union[Dict[Any, Any], None, + # Literal[_NoDefault.no_default]]"; expected + # "Optional[Dict[Any, Any]]" + downcast=downcast, # type: ignore[arg-type] ) else: if self.ndim == 1: @@ -7157,13 +7158,20 @@ def fillna( if k not in result: continue - # error: Item "None" of "Optional[Dict[Any, Any]]" has no - # attribute "get" - downcast_k = ( - downcast - if not is_dict - else downcast.get(k) # type: ignore[union-attr] - ) + if was_no_default: + downcast_k = lib.no_default + else: + downcast_k = ( + # error: Incompatible types in assignment (expression + # has type "Union[Dict[Any, Any], None, + # Literal[_NoDefault.no_default], Any]", variable has + # type "_NoDefault") + downcast # type: ignore[assignment] + if not is_dict + # error: Item "None" of "Optional[Dict[Any, Any]]" has + # no attribute "get" + else downcast.get(k) # type: ignore[union-attr] + ) res_k = result[k].fillna(v, limit=limit, downcast=downcast_k) @@ -7236,7 +7244,7 @@ def ffill( axis: None | Axis = ..., inplace: Literal[False] = ..., limit: None | int = ..., - downcast: dict | None = ..., + downcast: dict | None | lib.NoDefault = ..., ) -> Self: ... @@ -7247,7 +7255,7 @@ def ffill( axis: None | Axis = ..., inplace: Literal[True], limit: None | int = ..., - downcast: dict | None = ..., + downcast: dict | None | lib.NoDefault = ..., ) -> None: ... @@ -7258,7 +7266,7 @@ def ffill( axis: None | Axis = ..., inplace: bool_t = ..., limit: None | int = ..., - downcast: dict | None = ..., + downcast: dict | None | lib.NoDefault = ..., ) -> Self | None: ... @@ -7270,7 +7278,7 @@ def ffill( axis: None | Axis = None, inplace: bool_t = False, limit: None | int = None, - downcast: dict | None = None, + downcast: dict | None | lib.NoDefault = lib.no_default, ) -> Self | None: """ Synonym for :meth:`DataFrame.fillna` with ``method='ffill'``. @@ -7309,10 +7317,17 @@ def ffill( 3 3.0 dtype: float64 """ - self._deprecate_downcast(downcast) + downcast = self._deprecate_downcast(downcast, "ffill") return self._pad_or_backfill( - "ffill", axis=axis, inplace=inplace, limit=limit, downcast=downcast + "ffill", + axis=axis, + inplace=inplace, + limit=limit, + # error: Argument "downcast" to "_fillna_with_method" of "NDFrame" + # has incompatible type "Union[Dict[Any, Any], None, + # Literal[_NoDefault.no_default]]"; expected "Optional[Dict[Any, Any]]" + downcast=downcast, # type: ignore[arg-type] ) @final @@ -7323,7 +7338,7 @@ def pad( axis: None | Axis = None, inplace: bool_t = False, limit: None | int = None, - downcast: dict | None = None, + downcast: dict | None | lib.NoDefault = lib.no_default, ) -> Self | None: """ Synonym for :meth:`DataFrame.fillna` with ``method='ffill'``. @@ -7352,7 +7367,7 @@ def bfill( axis: None | Axis = ..., inplace: Literal[False] = ..., limit: None | int = ..., - downcast: dict | None = ..., + downcast: dict | None | lib.NoDefault = ..., ) -> Self: ... @@ -7363,7 +7378,7 @@ def bfill( axis: None | Axis = ..., inplace: Literal[True], limit: None | int = ..., - downcast: dict | None = ..., + downcast: dict | None | lib.NoDefault = ..., ) -> None: ... @@ -7374,7 +7389,7 @@ def bfill( axis: None | Axis = ..., inplace: bool_t = ..., limit: None | int = ..., - downcast: dict | None = ..., + downcast: dict | None | lib.NoDefault = ..., ) -> Self | None: ... @@ -7386,7 +7401,7 @@ def bfill( axis: None | Axis = None, inplace: bool_t = False, limit: None | int = None, - downcast: dict | None = None, + downcast: dict | None | lib.NoDefault = lib.no_default, ) -> Self | None: """ Synonym for :meth:`DataFrame.fillna` with ``method='bfill'``. @@ -7407,12 +7422,6 @@ def bfill( 2 2.0 3 2.0 dtype: float64 - >>> s.bfill(downcast='infer') - 0 1 - 1 2 - 2 2 - 3 2 - dtype: int64 >>> s.bfill(limit=1) 0 1.0 1 NaN @@ -7435,16 +7444,23 @@ def bfill( 1 4.0 5.0 2 4.0 7.0 3 4.0 7.0 - >>> df.bfill(downcast='infer', limit=1) - A B - 0 1.0 5 - 1 NaN 5 - 2 4.0 7 - 3 4.0 7 - """ - self._deprecate_downcast(downcast) + >>> df.bfill(limit=1) + A B + 0 1.0 5.0 + 1 NaN 5.0 + 2 4.0 7.0 + 3 4.0 7.0 + """ + downcast = self._deprecate_downcast(downcast, "bfill") return self._pad_or_backfill( - "bfill", axis=axis, inplace=inplace, limit=limit, downcast=downcast + "bfill", + axis=axis, + inplace=inplace, + limit=limit, + # error: Argument "downcast" to "_fillna_with_method" of "NDFrame" + # has incompatible type "Union[Dict[Any, Any], None, + # Literal[_NoDefault.no_default]]"; expected "Optional[Dict[Any, Any]]" + downcast=downcast, # type: ignore[arg-type] ) @final @@ -7455,7 +7471,7 @@ def backfill( axis: None | Axis = None, inplace: bool_t = False, limit: None | int = None, - downcast: dict | None = None, + downcast: dict | None | lib.NoDefault = lib.no_default, ) -> Self | None: """ Synonym for :meth:`DataFrame.fillna` with ``method='bfill'``. @@ -7780,7 +7796,7 @@ def interpolate( inplace: bool_t = False, limit_direction: Literal["forward", "backward", "both"] | None = None, limit_area: Literal["inside", "outside"] | None = None, - downcast: Literal["infer"] | None = None, + downcast: Literal["infer"] | None | lib.NoDefault = lib.no_default, **kwargs, ) -> Self | None: """ @@ -7851,6 +7867,9 @@ def interpolate( downcast : optional, 'infer' or None, defaults to None Downcast dtypes if possible. + + .. deprecated:: 2.1.0 + ``**kwargs`` : optional Keyword arguments to pass on to the interpolating function. @@ -7949,6 +7968,17 @@ def interpolate( 3 16.0 Name: d, dtype: float64 """ + if downcast is not lib.no_default: + # GH#40988 + warnings.warn( + f"The 'downcast' keyword in {type(self).__name__}.interpolate " + "is deprecated and will be removed in a future version. " + "Call result.infer_objects(copy=False) on the result instead.", + FutureWarning, + stacklevel=find_stack_level(), + ) + else: + downcast = None if downcast is not None and downcast != "infer": raise ValueError("downcast must be either None or 'infer'") diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 6c8e9c3fe9a75..78f8448cc7cb3 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -868,7 +868,7 @@ def fillna( axis: Axis | None | lib.NoDefault = lib.no_default, inplace: bool = False, limit: int | None = None, - downcast: dict | None = None, + downcast: dict | None | lib.NoDefault = lib.no_default, ) -> Series | None: """ Fill NA/NaN values using the specified method within groups. @@ -912,6 +912,8 @@ def fillna( or the string 'infer' which will try to downcast to an appropriate equal type (e.g. float64 to int64 if possible). + .. deprecated:: 2.1.0 + Returns ------- Series @@ -2390,7 +2392,7 @@ def fillna( axis: Axis | None | lib.NoDefault = lib.no_default, inplace: bool = False, limit: int | None = None, - downcast=None, + downcast=lib.no_default, ) -> DataFrame | None: """ Fill NA/NaN values using the specified method within groups. @@ -2434,6 +2436,8 @@ def fillna( or the string 'infer' which will try to downcast to an appropriate equal type (e.g. float64 to int64 if possible). + .. deprecated:: 2.1.0 + Returns ------- DataFrame diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 9566a2f113b36..382929958fb93 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -844,7 +844,7 @@ def interpolate( inplace: bool = False, limit_direction: Literal["forward", "backward", "both"] = "forward", limit_area=None, - downcast=None, + downcast=lib.no_default, **kwargs, ): """ @@ -917,6 +917,9 @@ def interpolate( downcast : optional, 'infer' or None, defaults to None Downcast dtypes if possible. + + .. deprecated::2.1.0 + ``**kwargs`` : optional Keyword arguments to pass on to the interpolating function. @@ -1000,6 +1003,7 @@ def interpolate( Note that the series erroneously increases between two anchors ``07:00:00`` and ``07:00:02``. """ + assert downcast is lib.no_default # just checking coverage result = self._upsample("asfreq") return result.interpolate( method=method, diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 07985a2744069..2852ca8cf576a 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -207,26 +207,30 @@ def __internal_pivot_table( to_unstack.append(i) else: to_unstack.append(name) - table = agged.unstack(to_unstack) + table = agged.unstack(to_unstack, fill_value=fill_value) if not dropna: if isinstance(table.index, MultiIndex): m = MultiIndex.from_arrays( cartesian_product(table.index.levels), names=table.index.names ) - table = table.reindex(m, axis=0) + table = table.reindex(m, axis=0, fill_value=fill_value) if isinstance(table.columns, MultiIndex): m = MultiIndex.from_arrays( cartesian_product(table.columns.levels), names=table.columns.names ) - table = table.reindex(m, axis=1) + table = table.reindex(m, axis=1, fill_value=fill_value) if sort is True and isinstance(table, ABCDataFrame): table = table.sort_index(axis=1) if fill_value is not None: - table = table.fillna(fill_value, downcast="infer") + table = table.fillna(fill_value) + if aggfunc is len and not observed and lib.is_integer(fill_value): + # TODO: can we avoid this? this used to be handled by + # downcast="infer" in fillna + table = table.astype(np.int64) if margins: if dropna: diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 7f44e329e6778..c2f835212529f 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -2038,9 +2038,11 @@ def test_td64arr_div_numeric_array( expected = [tdser.iloc[0, n] / vector[n] for n in range(len(vector))] expected = tm.box_expected(expected, xbox).astype(object) # We specifically expect timedelta64("NaT") here, not pd.NA - expected[2] = expected[2].fillna( - np.timedelta64("NaT", "ns"), downcast=False - ) + msg = "The 'downcast' keyword in fillna" + with tm.assert_produces_warning(FutureWarning, match=msg): + expected[2] = expected[2].fillna( + np.timedelta64("NaT", "ns"), downcast=False + ) else: expected = [tdser[n] / vector[n] for n in range(len(tdser))] expected = [ @@ -2122,7 +2124,9 @@ def test_td64arr_all_nat_div_object_dtype_numeric(self, box_with_array): if box_with_array is not Index: expected = tm.box_expected(expected, box_with_array).astype(object) if box_with_array in [Series, DataFrame]: - expected = expected.fillna(tdnat, downcast=False) # GH#18463 + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = expected.fillna(tdnat, downcast=False) # GH#18463 result = left / right tm.assert_equal(result, expected) diff --git a/pandas/tests/copy_view/test_interp_fillna.py b/pandas/tests/copy_view/test_interp_fillna.py index 5d4fd75df830c..5a4b958b2148d 100644 --- a/pandas/tests/copy_view/test_interp_fillna.py +++ b/pandas/tests/copy_view/test_interp_fillna.py @@ -218,7 +218,9 @@ def test_fillna_inplace(using_copy_on_write, downcast): arr_a = get_array(df, "a") arr_b = get_array(df, "b") - df.fillna(5.5, inplace=True, downcast=downcast) + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + df.fillna(5.5, inplace=True, downcast=downcast) assert np.shares_memory(get_array(df, "a"), arr_a) assert np.shares_memory(get_array(df, "b"), arr_b) if using_copy_on_write: diff --git a/pandas/tests/frame/methods/test_fillna.py b/pandas/tests/frame/methods/test_fillna.py index d340e048994a9..109520859af4d 100644 --- a/pandas/tests/frame/methods/test_fillna.py +++ b/pandas/tests/frame/methods/test_fillna.py @@ -292,20 +292,25 @@ def test_fillna_downcast(self): # GH#15277 # infer int64 from float64 df = DataFrame({"a": [1.0, np.nan]}) - result = df.fillna(0, downcast="infer") + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.fillna(0, downcast="infer") expected = DataFrame({"a": [1, 0]}) tm.assert_frame_equal(result, expected) # infer int64 from float64 when fillna value is a dict df = DataFrame({"a": [1.0, np.nan]}) - result = df.fillna({"a": 0}, downcast="infer") + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.fillna({"a": 0}, downcast="infer") expected = DataFrame({"a": [1, 0]}) tm.assert_frame_equal(result, expected) def test_fillna_downcast_false(self, frame_or_series): # GH#45603 preserve object dtype with downcast=False obj = frame_or_series([1, 2, 3], dtype="object") - result = obj.fillna("", downcast=False) + msg = "The 'downcast' keyword in fillna" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = obj.fillna("", downcast=False) tm.assert_equal(result, obj) def test_fillna_downcast_noop(self, frame_or_series): @@ -316,7 +321,7 @@ def test_fillna_downcast_noop(self, frame_or_series): obj = frame_or_series([1, 2, 3], dtype=np.int64) - msg = "downcast other than None, False, and 'infer' are deprecated" + msg = "The 'downcast' keyword in fillna" with tm.assert_produces_warning(FutureWarning, match=msg): # GH#40988 res = obj.fillna("foo", downcast=np.dtype(np.int32)) @@ -324,7 +329,8 @@ def test_fillna_downcast_noop(self, frame_or_series): tm.assert_equal(res, expected) obj2 = obj.astype(np.float64) - res2 = obj2.fillna("foo", downcast="infer") + with tm.assert_produces_warning(FutureWarning, match=msg): + res2 = obj2.fillna("foo", downcast="infer") expected2 = obj # get back int64 tm.assert_equal(res2, expected2) @@ -648,7 +654,7 @@ def test_fillna_downcast_dict(self): # GH#40809 df = DataFrame({"col1": [1, np.nan]}) - msg = "downcast entries other than None, False, and 'infer' are deprecated" + msg = "The 'downcast' keyword in fillna" with tm.assert_produces_warning(FutureWarning, match=msg): result = df.fillna({"col1": 2}, downcast={"col1": "int64"}) expected = DataFrame({"col1": [1, 2]}) diff --git a/pandas/tests/frame/methods/test_interpolate.py b/pandas/tests/frame/methods/test_interpolate.py index 429f3678c34f9..ac862e5673411 100644 --- a/pandas/tests/frame/methods/test_interpolate.py +++ b/pandas/tests/frame/methods/test_interpolate.py @@ -165,7 +165,9 @@ def test_interp_combo(self): expected = Series([1.0, 2.0, 3.0, 4.0], name="A") tm.assert_series_equal(result, expected) - result = df["A"].interpolate(downcast="infer") + msg = "The 'downcast' keyword in Series.interpolate is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df["A"].interpolate(downcast="infer") expected = Series([1, 2, 3, 4], name="A") tm.assert_series_equal(result, expected) @@ -181,10 +183,14 @@ def test_inerpolate_invalid_downcast(self): ) msg = "downcast must be either None or 'infer'" + msg2 = "The 'downcast' keyword in DataFrame.interpolate is deprecated" + msg3 = "The 'downcast' keyword in Series.interpolate is deprecated" with pytest.raises(ValueError, match=msg): - df.interpolate(downcast="int64") + with tm.assert_produces_warning(FutureWarning, match=msg2): + df.interpolate(downcast="int64") with pytest.raises(ValueError, match=msg): - df["A"].interpolate(downcast="int64") + with tm.assert_produces_warning(FutureWarning, match=msg3): + df["A"].interpolate(downcast="int64") def test_interp_nan_idx(self): df = DataFrame({"A": [1, 2, np.nan, 4], "B": [np.nan, 2, 3, 4]}) @@ -246,7 +252,9 @@ def test_interp_alt_scipy(self): expected.loc[5, "A"] = 6 tm.assert_frame_equal(result, expected) - result = df.interpolate(method="barycentric", downcast="infer") + msg = "The 'downcast' keyword in DataFrame.interpolate is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.interpolate(method="barycentric", downcast="infer") tm.assert_frame_equal(result, expected.astype(np.int64)) result = df.interpolate(method="krogh") @@ -370,7 +378,9 @@ def test_interp_inplace(self, using_copy_on_write): tm.assert_frame_equal(result, expected) result = df.copy() - return_value = result["a"].interpolate(inplace=True, downcast="infer") + msg = "The 'downcast' keyword in Series.interpolate is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + return_value = result["a"].interpolate(inplace=True, downcast="infer") assert return_value is None if using_copy_on_write: tm.assert_frame_equal(result, expected_cow) @@ -406,11 +416,14 @@ def test_interp_ignore_all_good(self): } ) - result = df.interpolate(downcast=None) + msg = "The 'downcast' keyword in DataFrame.interpolate is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df.interpolate(downcast=None) tm.assert_frame_equal(result, expected) # all good - result = df[["B", "D"]].interpolate(downcast=None) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = df[["B", "D"]].interpolate(downcast=None) tm.assert_frame_equal(result, df[["B", "D"]]) def test_interp_time_inplace_axis(self): diff --git a/pandas/tests/frame/methods/test_quantile.py b/pandas/tests/frame/methods/test_quantile.py index d50b3e45969f0..0d9f4bd77d137 100644 --- a/pandas/tests/frame/methods/test_quantile.py +++ b/pandas/tests/frame/methods/test_quantile.py @@ -736,7 +736,9 @@ def test_quantile_empty_no_rows_dt64(self, interp_method): exp = exp.astype(object) if interpolation == "nearest": # GH#18463 TODO: would we prefer NaTs here? - exp = exp.fillna(np.nan, downcast=False) + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + exp = exp.fillna(np.nan, downcast=False) tm.assert_series_equal(res, exp) # both dt64tz diff --git a/pandas/tests/frame/test_logical_ops.py b/pandas/tests/frame/test_logical_ops.py index a58b79b5db111..2cc3b67e7ac02 100644 --- a/pandas/tests/frame/test_logical_ops.py +++ b/pandas/tests/frame/test_logical_ops.py @@ -165,7 +165,9 @@ def test_logical_with_nas(self): expected = Series([True, True]) tm.assert_series_equal(result, expected) - result = d["a"].fillna(False, downcast=False) | d["b"] + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = d["a"].fillna(False, downcast=False) | d["b"] expected = Series([True, True]) tm.assert_series_equal(result, expected) diff --git a/pandas/tests/groupby/test_categorical.py b/pandas/tests/groupby/test_categorical.py index c0704d9684574..b25950192018d 100644 --- a/pandas/tests/groupby/test_categorical.py +++ b/pandas/tests/groupby/test_categorical.py @@ -1235,7 +1235,9 @@ def test_seriesgroupby_observed_false_or_none(df_cat, observed, operation): expected = Series(data=[2, 4, np.nan, 1, np.nan, 3], index=index, name="C") if operation == "agg": - expected = expected.fillna(0, downcast="infer") + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + expected = expected.fillna(0, downcast="infer") grouped = df_cat.groupby(["A", "B"], observed=observed)["C"] result = getattr(grouped, operation)(sum) tm.assert_series_equal(result, expected) diff --git a/pandas/tests/groupby/transform/test_transform.py b/pandas/tests/groupby/transform/test_transform.py index 5caf3d2ac1d8b..cf41b4ff57331 100644 --- a/pandas/tests/groupby/transform/test_transform.py +++ b/pandas/tests/groupby/transform/test_transform.py @@ -764,10 +764,12 @@ def test_cython_transform_frame(request, op, args, targop, df_fix, gb_target): expected = expected.sort_index(axis=1) if op == "shift": - expected["string_missing"] = expected["string_missing"].fillna( - np.nan, downcast=False - ) - expected["string"] = expected["string"].fillna(np.nan, downcast=False) + depr_msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=depr_msg): + expected["string_missing"] = expected["string_missing"].fillna( + np.nan, downcast=False + ) + expected["string"] = expected["string"].fillna(np.nan, downcast=False) result = gb[expected.columns].transform(op, *args).sort_index(axis=1) tm.assert_frame_equal(result, expected) @@ -835,7 +837,9 @@ def test_cython_transform_frame_column( expected = gb[c].apply(targop) expected.name = c if c in ["string_missing", "string"]: - expected = expected.fillna(np.nan, downcast=False) + depr_msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=depr_msg): + expected = expected.fillna(np.nan, downcast=False) res = gb[c].transform(op, *args) tm.assert_series_equal(expected, res) diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index b6b21f9962876..11909bf56f05c 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -994,7 +994,9 @@ def test_round_trip_exception(self, datapath): result = read_json(StringIO(s)) res = result.reindex(index=df.index, columns=df.columns) - res = res.fillna(np.nan, downcast=False) + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = res.fillna(np.nan, downcast=False) tm.assert_frame_equal(res, df) @pytest.mark.network diff --git a/pandas/tests/io/test_html.py b/pandas/tests/io/test_html.py index d17e4b08b5a4d..0c1f3b58ad9df 100644 --- a/pandas/tests/io/test_html.py +++ b/pandas/tests/io/test_html.py @@ -1497,7 +1497,7 @@ def test_extract_links(self, arg): result = self.read_html(gh_13141_data, extract_links=arg)[0] expected = DataFrame([data_exp, foot_exp], columns=head_exp) - expected = expected.fillna(np.nan, downcast=False) + expected = expected.fillna(np.nan) tm.assert_frame_equal(result, expected) def test_extract_links_bad(self, spam_data): diff --git a/pandas/tests/series/methods/test_fillna.py b/pandas/tests/series/methods/test_fillna.py index 7665e4d015a45..aaffd52b78f95 100644 --- a/pandas/tests/series/methods/test_fillna.py +++ b/pandas/tests/series/methods/test_fillna.py @@ -175,13 +175,16 @@ def test_fillna_downcast(self): # GH#15277 # infer int64 from float64 ser = Series([1.0, np.nan]) - result = ser.fillna(0, downcast="infer") + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = ser.fillna(0, downcast="infer") expected = Series([1, 0]) tm.assert_series_equal(result, expected) # infer int64 from float64 when fillna value is a dict ser = Series([1.0, np.nan]) - result = ser.fillna({1: 0}, downcast="infer") + with tm.assert_produces_warning(FutureWarning, match=msg): + result = ser.fillna({1: 0}, downcast="infer") expected = Series([1, 0]) tm.assert_series_equal(result, expected) @@ -194,15 +197,21 @@ def test_fillna_downcast_infer_objects_to_numeric(self): ser = Series(arr) - res = ser.fillna(3, downcast="infer") + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.fillna(3, downcast="infer") expected = Series(np.arange(5), dtype=np.int64) tm.assert_series_equal(res, expected) - res = ser.ffill(downcast="infer") + msg = "The 'downcast' keyword in ffill is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.ffill(downcast="infer") expected = Series([0, 1, 2, 2, 4], dtype=np.int64) tm.assert_series_equal(res, expected) - res = ser.bfill(downcast="infer") + msg = "The 'downcast' keyword in bfill is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.bfill(downcast="infer") expected = Series([0, 1, 2, 4, 4], dtype=np.int64) tm.assert_series_equal(res, expected) @@ -210,14 +219,20 @@ def test_fillna_downcast_infer_objects_to_numeric(self): ser[2] = 2.5 expected = Series([0, 1, 2.5, 3, 4], dtype=np.float64) - res = ser.fillna(3, downcast="infer") + msg = "The 'downcast' keyword in fillna is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.fillna(3, downcast="infer") tm.assert_series_equal(res, expected) - res = ser.ffill(downcast="infer") + msg = "The 'downcast' keyword in ffill is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.ffill(downcast="infer") expected = Series([0, 1, 2.5, 2.5, 4], dtype=np.float64) tm.assert_series_equal(res, expected) - res = ser.bfill(downcast="infer") + msg = "The 'downcast' keyword in bfill is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + res = ser.bfill(downcast="infer") expected = Series([0, 1, 2.5, 4, 4], dtype=np.float64) tm.assert_series_equal(res, expected) diff --git a/pandas/tests/series/methods/test_interpolate.py b/pandas/tests/series/methods/test_interpolate.py index abd4cec5ad45c..4a8bf554742dd 100644 --- a/pandas/tests/series/methods/test_interpolate.py +++ b/pandas/tests/series/methods/test_interpolate.py @@ -290,21 +290,25 @@ def test_interp_scipy_basic(self): result = s.interpolate(method="slinear") tm.assert_series_equal(result, expected) - result = s.interpolate(method="slinear", downcast="infer") + msg = "The 'downcast' keyword in Series.interpolate is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.interpolate(method="slinear", downcast="infer") tm.assert_series_equal(result, expected) # nearest expected = Series([1, 3, 3, 12, 12, 25]) result = s.interpolate(method="nearest") tm.assert_series_equal(result, expected.astype("float")) - result = s.interpolate(method="nearest", downcast="infer") + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.interpolate(method="nearest", downcast="infer") tm.assert_series_equal(result, expected) # zero expected = Series([1, 3, 3, 12, 12, 25]) result = s.interpolate(method="zero") tm.assert_series_equal(result, expected.astype("float")) - result = s.interpolate(method="zero", downcast="infer") + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.interpolate(method="zero", downcast="infer") tm.assert_series_equal(result, expected) # quadratic # GH #15662. @@ -312,7 +316,8 @@ def test_interp_scipy_basic(self): result = s.interpolate(method="quadratic") tm.assert_series_equal(result, expected) - result = s.interpolate(method="quadratic", downcast="infer") + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.interpolate(method="quadratic", downcast="infer") tm.assert_series_equal(result, expected) # cubic expected = Series([1.0, 3.0, 6.8, 12.0, 18.2, 25.0]) diff --git a/pandas/tests/series/methods/test_reindex.py b/pandas/tests/series/methods/test_reindex.py index c801528e6ff97..cf042b310ff63 100644 --- a/pandas/tests/series/methods/test_reindex.py +++ b/pandas/tests/series/methods/test_reindex.py @@ -143,7 +143,9 @@ def test_reindex_pad2(): result = s.reindex(new_index).ffill() tm.assert_series_equal(result, expected.astype("float64")) - result = s.reindex(new_index).ffill(downcast="infer") + msg = "The 'downcast' keyword in ffill is deprecated" + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.reindex(new_index).ffill(downcast="infer") tm.assert_series_equal(result, expected) expected = Series([1, 5, 3, 5], index=new_index)