Skip to content

Commit

Permalink
DEPR: stricter downcast values in fillna (pandas-dev#53103)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and Yi Wei committed May 19, 2023
1 parent b9ba0ab commit cd66177
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
3 changes: 2 additions & 1 deletion doc/source/whatsnew/v2.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Deprecations
- Deprecated unused "closed" and "normalize" keywords in the :class:`DatetimeIndex` constructor (:issue:`52628`)
- Deprecated unused "closed" keyword in the :class:`TimedeltaIndex` constructor (:issue:`52628`)
- Deprecated logical operation between two non boolean :class:`Series` with different indexes always coercing the result to bool dtype. In a future version, this will maintain the return type of the inputs. (:issue:`52500`, :issue:`52538`)
- 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 constructing :class:`SparseArray` from scalar data, pass a sequence instead (:issue:`53039`)
-

Expand Down Expand Up @@ -361,7 +362,7 @@ Indexing

Missing
^^^^^^^
-
- Bug in :meth:`Series.interpolate` and :meth:`DataFrame.interpolate` failing to raise on invalid ``downcast`` keyword, which can be only ``None`` or "infer" (:issue:`53103`)
-

MultiIndex
Expand Down
24 changes: 23 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -6972,6 +6972,25 @@ def fillna(
inplace = validate_bool_kwarg(inplace, "inplace")
value, method = validate_fillna_kwargs(value, method)

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
warnings.warn(
"downcast other than None, False, and 'infer' are deprecated "
"and will raise in a future version",
FutureWarning,
stacklevel=find_stack_level(),
)

# set the default here, so functions examining the signaure
# can detect if something was set (e.g. in groupby) (GH9221)
if axis is None:
Expand Down Expand Up @@ -7548,7 +7567,7 @@ def interpolate(
inplace: bool_t = False,
limit_direction: Literal["forward", "backward", "both"] | None = None,
limit_area: Literal["inside", "outside"] | None = None,
downcast: str | None = None,
downcast: Literal["infer"] | None = None,
**kwargs,
) -> Self | None:
"""
Expand Down Expand Up @@ -7746,6 +7765,9 @@ def interpolate(
3 16.0
Name: d, dtype: float64
"""
if downcast is not None and downcast != "infer":
raise ValueError("downcast must be either None or 'infer'")

inplace = validate_bool_kwarg(inplace, "inplace")

axis = self._get_axis_number(axis)
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Any,
Callable,
Iterable,
Literal,
Sequence,
cast,
final,
Expand Down Expand Up @@ -1323,7 +1324,7 @@ def interpolate(
limit_direction: str = "forward",
limit_area: str | None = None,
fill_value: Any | None = None,
downcast: str | None = None,
downcast: Literal["infer"] | None = None,
using_cow: bool = False,
**kwargs,
) -> list[Block]:
Expand Down
15 changes: 12 additions & 3 deletions pandas/tests/frame/methods/test_fillna.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,11 @@ def test_fillna_downcast_noop(self, frame_or_series):
# 2) _can_hold_na + noop + not can_hold_element

obj = frame_or_series([1, 2, 3], dtype=np.int64)
res = obj.fillna("foo", downcast=np.dtype(np.int32))

msg = "downcast other than None, False, and 'infer' are deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
# GH#40988
res = obj.fillna("foo", downcast=np.dtype(np.int32))
expected = obj.astype(np.int32)
tm.assert_equal(res, expected)

Expand All @@ -306,7 +310,9 @@ def test_fillna_downcast_noop(self, frame_or_series):
expected2 = obj # get back int64
tm.assert_equal(res2, expected2)

res3 = obj2.fillna("foo", downcast=np.dtype(np.int32))
with tm.assert_produces_warning(FutureWarning, match=msg):
# GH#40988
res3 = obj2.fillna("foo", downcast=np.dtype(np.int32))
tm.assert_equal(res3, expected)

@pytest.mark.parametrize("columns", [["A", "A", "B"], ["A", "A"]])
Expand Down Expand Up @@ -605,7 +611,10 @@ def test_fill_corner(self, float_frame, float_string_frame):
def test_fillna_downcast_dict(self):
# GH#40809
df = DataFrame({"col1": [1, np.nan]})
result = df.fillna({"col1": 2}, downcast={"col1": "int64"})

msg = "downcast entries other than None, False, and 'infer' are deprecated"
with tm.assert_produces_warning(FutureWarning, match=msg):
result = df.fillna({"col1": 2}, downcast={"col1": "int64"})
expected = DataFrame({"col1": [1, 2]})
tm.assert_frame_equal(result, expected)

Expand Down
17 changes: 17 additions & 0 deletions pandas/tests/frame/methods/test_interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,23 @@ def test_interp_combo(self):
expected = Series([1, 2, 3, 4], name="A")
tm.assert_series_equal(result, expected)

def test_inerpolate_invalid_downcast(self):
# GH#53103
df = DataFrame(
{
"A": [1.0, 2.0, np.nan, 4.0],
"B": [1, 4, 9, np.nan],
"C": [1, 2, 3, 5],
"D": list("abcd"),
}
)

msg = "downcast must be either None or 'infer'"
with pytest.raises(ValueError, match=msg):
df.interpolate(downcast="int64")
with pytest.raises(ValueError, match=msg):
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]})
df = df.set_index("A")
Expand Down

0 comments on commit cd66177

Please sign in to comment.