Skip to content

DEPR: Series([np.nan], dtype='i8') silently ignoring dtype #45136

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 5 commits into from
Dec 31, 2021
Merged
Show file tree
Hide file tree
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: 2 additions & 0 deletions doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -656,8 +656,10 @@ Other Deprecations
- Deprecated ``numeric_only=None`` in :meth:`DataFrame.rank`; in a future version ``numeric_only`` must be either ``True`` or ``False`` (the default) (:issue:`45036`)
- Deprecated the behavior of :meth:`Timestamp.utcfromtimestamp`, in the future it will return a timezone-aware UTC :class:`Timestamp` (:issue:`22451`)
- Deprecated :meth:`NaT.freq` (:issue:`45071`)
- Deprecated behavior of :class:`Series` and :class:`DataFrame` construction when passed float-dtype data containing ``NaN`` and an integer dtype ignoring the dtype argument; in a future version this will raise (:issue:`40110`)
-


.. ---------------------------------------------------------------------------

.. _whatsnew_140.performance:
Expand Down
9 changes: 9 additions & 0 deletions pandas/core/construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,15 @@ def sanitize_array(
try:
subarr = _try_cast(data, dtype, copy, True)
except IntCastingNaNError:
warnings.warn(
"In a future version, passing float-dtype values containing NaN "
"and an integer dtype will raise IntCastingNaNError "
"(subclass of ValueError) instead of silently ignoring the "
"passed dtype. To retain the old behavior, call Series(arr) or "
"DataFrame(arr) without passing a dtype.",
FutureWarning,
stacklevel=find_stack_level(),
)
subarr = np.array(data, copy=copy)
except ValueError:
if not raise_cast_failure:
Expand Down
29 changes: 23 additions & 6 deletions pandas/tests/frame/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,14 @@ def test_constructor_dict_with_tzaware_scalar(self):
def test_construct_ndarray_with_nas_and_int_dtype(self):
# GH#26919 match Series by not casting np.nan to meaningless int
arr = np.array([[1, np.nan], [2, 3]])
df = DataFrame(arr, dtype="i8")
with tm.assert_produces_warning(FutureWarning):
df = DataFrame(arr, dtype="i8")
assert df.values.dtype == arr.dtype
assert isna(df.iloc[0, 1])

# check this matches Series behavior
ser = Series(arr[0], dtype="i8", name=0)
with tm.assert_produces_warning(FutureWarning):
ser = Series(arr[0], dtype="i8", name=0)
expected = df.iloc[0]
tm.assert_series_equal(ser, expected)

Expand Down Expand Up @@ -937,7 +939,11 @@ def _check_basic_constructor(self, empty):
assert len(frame.index) == 3
assert len(frame.columns) == 1

frame = DataFrame(mat, columns=["A", "B", "C"], index=[1, 2], dtype=np.int64)
warn = None if empty is np.ones else FutureWarning
with tm.assert_produces_warning(warn):
frame = DataFrame(
mat, columns=["A", "B", "C"], index=[1, 2], dtype=np.int64
)
if empty is np.ones:
# passing dtype casts
assert frame.values.dtype == np.int64
Expand Down Expand Up @@ -1766,7 +1772,9 @@ def test_constructor_mix_series_nonseries(self, float_frame):
DataFrame({"A": float_frame["A"], "B": list(float_frame["B"])[:-2]})

def test_constructor_miscast_na_int_dtype(self):
df = DataFrame([[np.nan, 1], [1, 0]], dtype=np.int64)
msg = "float-dtype values containing NaN and an integer dtype"
with tm.assert_produces_warning(FutureWarning, match=msg):
df = DataFrame([[np.nan, 1], [1, 0]], dtype=np.int64)
expected = DataFrame([[np.nan, 1], [1, 0]])
tm.assert_frame_equal(df, expected)

Expand Down Expand Up @@ -2713,10 +2721,19 @@ def test_floating_values_integer_dtype(self):
# if they can be cast losslessly, no warning
DataFrame(arr.round(), dtype="i8")

# with NaNs, we already have the correct behavior, so no warning
# with NaNs, we go through a different path with a different warning
arr[0, 0] = np.nan
with tm.assert_produces_warning(None):
msg = "passing float-dtype values containing NaN"
with tm.assert_produces_warning(FutureWarning, match=msg):
DataFrame(arr, dtype="i8")
with tm.assert_produces_warning(FutureWarning, match=msg):
Series(arr[0], dtype="i8")
# The future (raising) behavior matches what we would get via astype:
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
with pytest.raises(ValueError, match=msg):
DataFrame(arr).astype("i8")
with pytest.raises(ValueError, match=msg):
Series(arr[0]).astype("i8")


class TestDataFrameConstructorWithDatetimeTZ:
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/frame/test_stack_unstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,8 +1046,8 @@ def _test_stack_with_multiindex(multiindex):
names=[None, "Lower"],
),
columns=Index(["B", "C"], name="Upper"),
dtype=df.dtypes[0],
)
expected["B"] = expected["B"].astype(df.dtypes[0])
tm.assert_frame_equal(result, expected)

@pytest.mark.parametrize("ordered", [False, True])
Expand Down
6 changes: 4 additions & 2 deletions pandas/tests/series/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,8 +652,10 @@ def test_constructor_sanitize(self):
s = Series(np.array([1.0, 1.0, 8.0]), dtype="i8")
assert s.dtype == np.dtype("i8")

s = Series(np.array([1.0, 1.0, np.nan]), copy=True, dtype="i8")
assert s.dtype == np.dtype("f8")
msg = "float-dtype values containing NaN and an integer dtype"
with tm.assert_produces_warning(FutureWarning, match=msg):
ser = Series(np.array([1.0, 1.0, np.nan]), copy=True, dtype="i8")
assert ser.dtype == np.dtype("f8")

def test_constructor_copy(self):
# GH15125
Expand Down