Skip to content

Commit

Permalink
BUG: Fix inserting of wrong-dtyped NaT, closes #27297 (#27311)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and jreback committed Jul 22, 2019
1 parent 41e3b29 commit 76247c1
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 2 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Categorical

Datetimelike
^^^^^^^^^^^^

- Bug in :meth:`Series.__setitem__` incorrectly casting ``np.timedelta64("NaT")`` to ``np.datetime64("NaT")`` when inserting into a :class:`Series` with datetime64 dtype (:issue:`27311`)
-
-

Expand Down
3 changes: 3 additions & 0 deletions pandas/_libs/index.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,9 @@ cpdef convert_scalar(ndarray arr, object value):
pass
elif isinstance(value, (datetime, np.datetime64, date)):
return Timestamp(value).value
elif util.is_timedelta64_object(value):
# exclude np.timedelta64("NaT") from value != value below
pass
elif value is None or value != value:
return NPY_NAT
elif isinstance(value, str):
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 @@ -2589,8 +2589,9 @@ def setitem(self, indexer, value):
try:
return super().setitem(indexer, value)
except (ValueError, TypeError):
obj_vals = self.values.astype(object)
newb = make_block(
self.values.astype(object), placement=self.mgr_locs, klass=ObjectBlock
obj_vals, placement=self.mgr_locs, klass=ObjectBlock, ndim=self.ndim
)
return newb.setitem(indexer, value)

Expand Down
32 changes: 32 additions & 0 deletions pandas/tests/series/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,38 @@ def test_timedelta_assignment():
tm.assert_series_equal(s, expected)


@pytest.mark.parametrize(
"nat_val,should_cast",
[
(pd.NaT, True),
(np.timedelta64("NaT", "ns"), False),
(np.datetime64("NaT", "ns"), True),
],
)
@pytest.mark.parametrize("tz", [None, "UTC"])
def test_dt64_series_assign_nat(nat_val, should_cast, tz):
# some nat-like values should be cast to datetime64 when inserting
# into a datetime64 series. Others should coerce to object
# and retain their dtypes.
dti = pd.date_range("2016-01-01", periods=3, tz=tz)
base = pd.Series(dti)
expected = pd.Series([pd.NaT] + list(dti[1:]), dtype=dti.dtype)
if not should_cast:
expected = expected.astype(object)

ser = base.copy(deep=True)
ser[0] = nat_val
tm.assert_series_equal(ser, expected)

ser = base.copy(deep=True)
ser.loc[0] = nat_val
tm.assert_series_equal(ser, expected)

ser = base.copy(deep=True)
ser.iloc[0] = nat_val
tm.assert_series_equal(ser, expected)


@pytest.mark.parametrize(
"nat_val,should_cast",
[
Expand Down

0 comments on commit 76247c1

Please sign in to comment.