Skip to content
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v2.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,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`)
Expand Down Expand Up @@ -283,7 +284,6 @@ Deprecations
- Deprecated :func:`value_counts`, use ``pd.Series(obj).value_counts()`` instead (:issue:`47862`)
- 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 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 constructing :class:`SparseArray` from scalar data, pass a sequence instead (:issue:`53039`)
Expand Down
133 changes: 80 additions & 53 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6804,25 +6804,18 @@ 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.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we suggest using to_numeric(downcast) here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will update

FutureWarning,
stacklevel=find_stack_level(),
)
else:
downcast = None
return downcast

@final
def _fillna_with_method(
Expand Down Expand Up @@ -6911,7 +6904,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.
Expand Down Expand Up @@ -7030,7 +7023,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)
Expand All @@ -7047,7 +7041,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:
Expand Down Expand Up @@ -7091,13 +7089,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)

Expand Down Expand Up @@ -7174,7 +7179,7 @@ def ffill(
axis: None | Axis = ...,
inplace: Literal[False] = ...,
limit: None | int = ...,
downcast: dict | None = ...,
downcast: dict | None | lib.NoDefault = ...,
) -> Self:
...

Expand All @@ -7185,7 +7190,7 @@ def ffill(
axis: None | Axis = ...,
inplace: Literal[True],
limit: None | int = ...,
downcast: dict | None = ...,
downcast: dict | None | lib.NoDefault = ...,
) -> None:
...

Expand All @@ -7196,7 +7201,7 @@ def ffill(
axis: None | Axis = ...,
inplace: bool_t = ...,
limit: None | int = ...,
downcast: dict | None = ...,
downcast: dict | None | lib.NoDefault = ...,
) -> Self | None:
...

Expand All @@ -7208,7 +7213,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'``.
Expand Down Expand Up @@ -7247,10 +7252,17 @@ def ffill(
3 3.0
dtype: float64
"""
self._deprecate_downcast(downcast)
downcast = self._deprecate_downcast(downcast, "ffill")

return self._fillna_with_method(
"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
Expand All @@ -7261,7 +7273,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'``.
Expand Down Expand Up @@ -7290,7 +7302,7 @@ def bfill(
axis: None | Axis = ...,
inplace: Literal[False] = ...,
limit: None | int = ...,
downcast: dict | None = ...,
downcast: dict | None | lib.NoDefault = ...,
) -> Self:
...

Expand All @@ -7301,7 +7313,7 @@ def bfill(
axis: None | Axis = ...,
inplace: Literal[True],
limit: None | int = ...,
downcast: dict | None = ...,
downcast: dict | None | lib.NoDefault = ...,
) -> None:
...

Expand All @@ -7312,7 +7324,7 @@ def bfill(
axis: None | Axis = ...,
inplace: bool_t = ...,
limit: None | int = ...,
downcast: dict | None = ...,
downcast: dict | None | lib.NoDefault = ...,
) -> Self | None:
...

Expand All @@ -7324,7 +7336,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'``.
Expand All @@ -7345,12 +7357,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
Expand All @@ -7373,16 +7379,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._fillna_with_method(
"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
Expand All @@ -7393,7 +7406,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'``.
Expand Down Expand Up @@ -7718,7 +7731,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:
"""
Expand Down Expand Up @@ -7789,6 +7802,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.

Expand Down Expand Up @@ -7887,6 +7903,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'")

Expand Down
8 changes: 6 additions & 2 deletions pandas/core/groupby/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,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.
Expand Down Expand Up @@ -905,6 +905,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
Expand Down Expand Up @@ -2383,7 +2385,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.
Expand Down Expand Up @@ -2427,6 +2429,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
Expand Down
6 changes: 5 additions & 1 deletion pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ def interpolate(
inplace: bool = False,
limit_direction: Literal["forward", "backward", "both"] = "forward",
limit_area=None,
downcast=None,
downcast=lib.no_default,
**kwargs,
):
"""
Expand Down Expand Up @@ -914,6 +914,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.

Expand Down Expand Up @@ -997,6 +1000,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,
Expand Down
Loading