Skip to content

DEPR: downcast keyword #53671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 29, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v2.1.0.rst
Original file line number Diff line number Diff line change
@@ -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`)
136 changes: 83 additions & 53 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
@@ -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'")

8 changes: 6 additions & 2 deletions pandas/core/groupby/generic.py
Original file line number Diff line number Diff line change
@@ -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
6 changes: 5 additions & 1 deletion pandas/core/resample.py
Original file line number Diff line number Diff line change
@@ -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,
Loading