Skip to content

Commit 542e590

Browse files
jbrockmendelim-vinicius
authored and
im-vinicius
committed
DEPR: downcast keyword (pandas-dev#53671)
1 parent 0d46877 commit 542e590

18 files changed

+203
-102
lines changed

doc/source/whatsnew/v2.1.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ Deprecations
256256
- 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`)
257257
- Deprecated passing a :class:`DataFrame` to :meth:`DataFrame.from_records`, use :meth:`DataFrame.set_index` or :meth:`DataFrame.drop` instead (:issue:`51353`)
258258
- Deprecated silently dropping unrecognized timezones when parsing strings to datetimes (:issue:`18702`)
259+
- 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`)
259260
- 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`)
260261
- Deprecated the ``axis`` keyword in :meth:`DataFrame.resample`, :meth:`Series.resample` (:issue:`51778`)
261262
- 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`)
@@ -293,7 +294,6 @@ Deprecations
293294
- Deprecated :meth:`Series.first` and :meth:`DataFrame.first` (please create a mask and filter using ``.loc`` instead) (:issue:`45908`)
294295
- Deprecated :meth:`Series.interpolate` and :meth:`DataFrame.interpolate` for object-dtype (:issue:`53631`)
295296
- Deprecated :meth:`Series.last` and :meth:`DataFrame.last` (please create a mask and filter using ``.loc`` instead) (:issue:`53692`)
296-
- 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`)
297297
- 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`)
298298
- 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`)
299299
- Deprecated bytes input to :func:`read_excel`. To read a file path, use a string or path-like object. (:issue:`53767`)

pandas/core/generic.py

+83-53
Original file line numberDiff line numberDiff line change
@@ -6871,25 +6871,21 @@ def convert_dtypes(
68716871
# ----------------------------------------------------------------------
68726872
# Filling NA's
68736873

6874-
def _deprecate_downcast(self, downcast) -> None:
6875-
if isinstance(downcast, dict):
6876-
# GH#40988
6877-
for dc in downcast.values():
6878-
if dc is not None and dc is not False and dc != "infer":
6879-
warnings.warn(
6880-
"downcast entries other than None, False, and 'infer' "
6881-
"are deprecated and will raise in a future version",
6882-
FutureWarning,
6883-
stacklevel=find_stack_level(),
6884-
)
6885-
elif downcast is not None and downcast is not False and downcast != "infer":
6886-
# GH#40988
6874+
def _deprecate_downcast(self, downcast, method_name: str):
6875+
# GH#40988
6876+
if downcast is not lib.no_default:
68876877
warnings.warn(
6888-
"downcast other than None, False, and 'infer' are deprecated "
6889-
"and will raise in a future version",
6878+
f"The 'downcast' keyword in {method_name} is deprecated and "
6879+
"will be removed in a future version. Use "
6880+
"res.infer_objects(copy=False) to infer non-object dtype, or "
6881+
"pd.to_numeric with the 'downcast' keyword to downcast numeric "
6882+
"results.",
68906883
FutureWarning,
68916884
stacklevel=find_stack_level(),
68926885
)
6886+
else:
6887+
downcast = None
6888+
return downcast
68936889

68946890
@final
68956891
def _pad_or_backfill(
@@ -6978,7 +6974,7 @@ def fillna(
69786974
axis: Axis | None = None,
69796975
inplace: bool_t = False,
69806976
limit: int | None = None,
6981-
downcast: dict | None = None,
6977+
downcast: dict | None | lib.NoDefault = lib.no_default,
69826978
) -> Self | None:
69836979
"""
69846980
Fill NA/NaN values using the specified method.
@@ -7097,7 +7093,8 @@ def fillna(
70977093
stacklevel=find_stack_level(),
70987094
)
70997095

7100-
self._deprecate_downcast(downcast)
7096+
was_no_default = downcast is lib.no_default
7097+
downcast = self._deprecate_downcast(downcast, "fillna")
71017098

71027099
# set the default here, so functions examining the signaure
71037100
# can detect if something was set (e.g. in groupby) (GH9221)
@@ -7114,7 +7111,11 @@ def fillna(
71147111
axis=axis,
71157112
limit=limit,
71167113
inplace=inplace,
7117-
downcast=downcast,
7114+
# error: Argument "downcast" to "_fillna_with_method" of "NDFrame"
7115+
# has incompatible type "Union[Dict[Any, Any], None,
7116+
# Literal[_NoDefault.no_default]]"; expected
7117+
# "Optional[Dict[Any, Any]]"
7118+
downcast=downcast, # type: ignore[arg-type]
71187119
)
71197120
else:
71207121
if self.ndim == 1:
@@ -7158,13 +7159,20 @@ def fillna(
71587159
if k not in result:
71597160
continue
71607161

7161-
# error: Item "None" of "Optional[Dict[Any, Any]]" has no
7162-
# attribute "get"
7163-
downcast_k = (
7164-
downcast
7165-
if not is_dict
7166-
else downcast.get(k) # type: ignore[union-attr]
7167-
)
7162+
if was_no_default:
7163+
downcast_k = lib.no_default
7164+
else:
7165+
downcast_k = (
7166+
# error: Incompatible types in assignment (expression
7167+
# has type "Union[Dict[Any, Any], None,
7168+
# Literal[_NoDefault.no_default], Any]", variable has
7169+
# type "_NoDefault")
7170+
downcast # type: ignore[assignment]
7171+
if not is_dict
7172+
# error: Item "None" of "Optional[Dict[Any, Any]]" has
7173+
# no attribute "get"
7174+
else downcast.get(k) # type: ignore[union-attr]
7175+
)
71687176

71697177
res_k = result[k].fillna(v, limit=limit, downcast=downcast_k)
71707178

@@ -7237,7 +7245,7 @@ def ffill(
72377245
axis: None | Axis = ...,
72387246
inplace: Literal[False] = ...,
72397247
limit: None | int = ...,
7240-
downcast: dict | None = ...,
7248+
downcast: dict | None | lib.NoDefault = ...,
72417249
) -> Self:
72427250
...
72437251

@@ -7248,7 +7256,7 @@ def ffill(
72487256
axis: None | Axis = ...,
72497257
inplace: Literal[True],
72507258
limit: None | int = ...,
7251-
downcast: dict | None = ...,
7259+
downcast: dict | None | lib.NoDefault = ...,
72527260
) -> None:
72537261
...
72547262

@@ -7259,7 +7267,7 @@ def ffill(
72597267
axis: None | Axis = ...,
72607268
inplace: bool_t = ...,
72617269
limit: None | int = ...,
7262-
downcast: dict | None = ...,
7270+
downcast: dict | None | lib.NoDefault = ...,
72637271
) -> Self | None:
72647272
...
72657273

@@ -7271,7 +7279,7 @@ def ffill(
72717279
axis: None | Axis = None,
72727280
inplace: bool_t = False,
72737281
limit: None | int = None,
7274-
downcast: dict | None = None,
7282+
downcast: dict | None | lib.NoDefault = lib.no_default,
72757283
) -> Self | None:
72767284
"""
72777285
Synonym for :meth:`DataFrame.fillna` with ``method='ffill'``.
@@ -7310,10 +7318,17 @@ def ffill(
73107318
3 3.0
73117319
dtype: float64
73127320
"""
7313-
self._deprecate_downcast(downcast)
7321+
downcast = self._deprecate_downcast(downcast, "ffill")
73147322

73157323
return self._pad_or_backfill(
7316-
"ffill", axis=axis, inplace=inplace, limit=limit, downcast=downcast
7324+
"ffill",
7325+
axis=axis,
7326+
inplace=inplace,
7327+
limit=limit,
7328+
# error: Argument "downcast" to "_fillna_with_method" of "NDFrame"
7329+
# has incompatible type "Union[Dict[Any, Any], None,
7330+
# Literal[_NoDefault.no_default]]"; expected "Optional[Dict[Any, Any]]"
7331+
downcast=downcast, # type: ignore[arg-type]
73177332
)
73187333

73197334
@final
@@ -7324,7 +7339,7 @@ def pad(
73247339
axis: None | Axis = None,
73257340
inplace: bool_t = False,
73267341
limit: None | int = None,
7327-
downcast: dict | None = None,
7342+
downcast: dict | None | lib.NoDefault = lib.no_default,
73287343
) -> Self | None:
73297344
"""
73307345
Synonym for :meth:`DataFrame.fillna` with ``method='ffill'``.
@@ -7353,7 +7368,7 @@ def bfill(
73537368
axis: None | Axis = ...,
73547369
inplace: Literal[False] = ...,
73557370
limit: None | int = ...,
7356-
downcast: dict | None = ...,
7371+
downcast: dict | None | lib.NoDefault = ...,
73577372
) -> Self:
73587373
...
73597374

@@ -7364,7 +7379,7 @@ def bfill(
73647379
axis: None | Axis = ...,
73657380
inplace: Literal[True],
73667381
limit: None | int = ...,
7367-
downcast: dict | None = ...,
7382+
downcast: dict | None | lib.NoDefault = ...,
73687383
) -> None:
73697384
...
73707385

@@ -7375,7 +7390,7 @@ def bfill(
73757390
axis: None | Axis = ...,
73767391
inplace: bool_t = ...,
73777392
limit: None | int = ...,
7378-
downcast: dict | None = ...,
7393+
downcast: dict | None | lib.NoDefault = ...,
73797394
) -> Self | None:
73807395
...
73817396

@@ -7387,7 +7402,7 @@ def bfill(
73877402
axis: None | Axis = None,
73887403
inplace: bool_t = False,
73897404
limit: None | int = None,
7390-
downcast: dict | None = None,
7405+
downcast: dict | None | lib.NoDefault = lib.no_default,
73917406
) -> Self | None:
73927407
"""
73937408
Synonym for :meth:`DataFrame.fillna` with ``method='bfill'``.
@@ -7408,12 +7423,6 @@ def bfill(
74087423
2 2.0
74097424
3 2.0
74107425
dtype: float64
7411-
>>> s.bfill(downcast='infer')
7412-
0 1
7413-
1 2
7414-
2 2
7415-
3 2
7416-
dtype: int64
74177426
>>> s.bfill(limit=1)
74187427
0 1.0
74197428
1 NaN
@@ -7436,16 +7445,23 @@ def bfill(
74367445
1 4.0 5.0
74377446
2 4.0 7.0
74387447
3 4.0 7.0
7439-
>>> df.bfill(downcast='infer', limit=1)
7440-
A B
7441-
0 1.0 5
7442-
1 NaN 5
7443-
2 4.0 7
7444-
3 4.0 7
7445-
"""
7446-
self._deprecate_downcast(downcast)
7448+
>>> df.bfill(limit=1)
7449+
A B
7450+
0 1.0 5.0
7451+
1 NaN 5.0
7452+
2 4.0 7.0
7453+
3 4.0 7.0
7454+
"""
7455+
downcast = self._deprecate_downcast(downcast, "bfill")
74477456
return self._pad_or_backfill(
7448-
"bfill", axis=axis, inplace=inplace, limit=limit, downcast=downcast
7457+
"bfill",
7458+
axis=axis,
7459+
inplace=inplace,
7460+
limit=limit,
7461+
# error: Argument "downcast" to "_fillna_with_method" of "NDFrame"
7462+
# has incompatible type "Union[Dict[Any, Any], None,
7463+
# Literal[_NoDefault.no_default]]"; expected "Optional[Dict[Any, Any]]"
7464+
downcast=downcast, # type: ignore[arg-type]
74497465
)
74507466

74517467
@final
@@ -7456,7 +7472,7 @@ def backfill(
74567472
axis: None | Axis = None,
74577473
inplace: bool_t = False,
74587474
limit: None | int = None,
7459-
downcast: dict | None = None,
7475+
downcast: dict | None | lib.NoDefault = lib.no_default,
74607476
) -> Self | None:
74617477
"""
74627478
Synonym for :meth:`DataFrame.fillna` with ``method='bfill'``.
@@ -7761,7 +7777,7 @@ def interpolate(
77617777
inplace: bool_t = False,
77627778
limit_direction: Literal["forward", "backward", "both"] | None = None,
77637779
limit_area: Literal["inside", "outside"] | None = None,
7764-
downcast: Literal["infer"] | None = None,
7780+
downcast: Literal["infer"] | None | lib.NoDefault = lib.no_default,
77657781
**kwargs,
77667782
) -> Self | None:
77677783
"""
@@ -7832,6 +7848,9 @@ def interpolate(
78327848
78337849
downcast : optional, 'infer' or None, defaults to None
78347850
Downcast dtypes if possible.
7851+
7852+
.. deprecated:: 2.1.0
7853+
78357854
``**kwargs`` : optional
78367855
Keyword arguments to pass on to the interpolating function.
78377856
@@ -7930,6 +7949,17 @@ def interpolate(
79307949
3 16.0
79317950
Name: d, dtype: float64
79327951
"""
7952+
if downcast is not lib.no_default:
7953+
# GH#40988
7954+
warnings.warn(
7955+
f"The 'downcast' keyword in {type(self).__name__}.interpolate "
7956+
"is deprecated and will be removed in a future version. "
7957+
"Call result.infer_objects(copy=False) on the result instead.",
7958+
FutureWarning,
7959+
stacklevel=find_stack_level(),
7960+
)
7961+
else:
7962+
downcast = None
79337963
if downcast is not None and downcast != "infer":
79347964
raise ValueError("downcast must be either None or 'infer'")
79357965

pandas/core/groupby/generic.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ def fillna(
868868
axis: Axis | None | lib.NoDefault = lib.no_default,
869869
inplace: bool = False,
870870
limit: int | None = None,
871-
downcast: dict | None = None,
871+
downcast: dict | None | lib.NoDefault = lib.no_default,
872872
) -> Series | None:
873873
"""
874874
Fill NA/NaN values using the specified method within groups.
@@ -912,6 +912,8 @@ def fillna(
912912
or the string 'infer' which will try to downcast to an appropriate
913913
equal type (e.g. float64 to int64 if possible).
914914
915+
.. deprecated:: 2.1.0
916+
915917
Returns
916918
-------
917919
Series
@@ -2390,7 +2392,7 @@ def fillna(
23902392
axis: Axis | None | lib.NoDefault = lib.no_default,
23912393
inplace: bool = False,
23922394
limit: int | None = None,
2393-
downcast=None,
2395+
downcast=lib.no_default,
23942396
) -> DataFrame | None:
23952397
"""
23962398
Fill NA/NaN values using the specified method within groups.
@@ -2434,6 +2436,8 @@ def fillna(
24342436
or the string 'infer' which will try to downcast to an appropriate
24352437
equal type (e.g. float64 to int64 if possible).
24362438
2439+
.. deprecated:: 2.1.0
2440+
24372441
Returns
24382442
-------
24392443
DataFrame

pandas/core/resample.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ def interpolate(
892892
inplace: bool = False,
893893
limit_direction: Literal["forward", "backward", "both"] = "forward",
894894
limit_area=None,
895-
downcast=None,
895+
downcast=lib.no_default,
896896
**kwargs,
897897
):
898898
"""
@@ -965,6 +965,9 @@ def interpolate(
965965
966966
downcast : optional, 'infer' or None, defaults to None
967967
Downcast dtypes if possible.
968+
969+
.. deprecated::2.1.0
970+
968971
``**kwargs`` : optional
969972
Keyword arguments to pass on to the interpolating function.
970973
@@ -1048,6 +1051,7 @@ def interpolate(
10481051
Note that the series erroneously increases between two anchors
10491052
``07:00:00`` and ``07:00:02``.
10501053
"""
1054+
assert downcast is lib.no_default # just checking coverage
10511055
result = self._upsample("asfreq")
10521056
return result.interpolate(
10531057
method=method,

0 commit comments

Comments
 (0)