Skip to content

Commit 810fa77

Browse files
inmoonlightjreback
authored andcommitted
Assignment of column via .loc for numpy non-ns datetimes (#27928)
1 parent f61deb9 commit 810fa77

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

doc/source/whatsnew/v0.25.2.rst

-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ Indexing
5252
-
5353
-
5454
-
55-
-
5655

5756
Missing
5857
^^^^^^^

doc/source/whatsnew/v1.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ Indexing
170170

171171
- Bug in assignment using a reverse slicer (:issue:`26939`)
172172
- Bug in reindexing a :meth:`PeriodIndex` with another type of index that contained a `Period` (:issue:`28323`) (:issue:`28337`)
173+
- Fix assignment of column via `.loc` with numpy non-ns datetime type (:issue:`27395`)
173174

174175
Missing
175176
^^^^^^^

pandas/core/dtypes/cast.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,10 @@ def maybe_cast_to_datetime(value, dtype, errors="raise"):
10291029
)
10301030

10311031
if is_datetime64 and not is_dtype_equal(dtype, _NS_DTYPE):
1032-
if dtype.name in ("datetime64", "datetime64[ns]"):
1032+
1033+
# pandas supports dtype whose granularity is less than [ns]
1034+
# e.g., [ps], [fs], [as]
1035+
if dtype <= np.dtype("M8[ns]"):
10331036
if dtype.name == "datetime64":
10341037
raise ValueError(msg.format(dtype=dtype.name))
10351038
dtype = _NS_DTYPE
@@ -1047,7 +1050,10 @@ def maybe_cast_to_datetime(value, dtype, errors="raise"):
10471050
value = [value]
10481051

10491052
elif is_timedelta64 and not is_dtype_equal(dtype, _TD_DTYPE):
1050-
if dtype.name in ("timedelta64", "timedelta64[ns]"):
1053+
1054+
# pandas supports dtype whose granularity is less than [ns]
1055+
# e.g., [ps], [fs], [as]
1056+
if dtype <= np.dtype("m8[ns]"):
10511057
if dtype.name == "timedelta64":
10521058
raise ValueError(msg.format(dtype=dtype.name))
10531059
dtype = _TD_DTYPE

pandas/tests/indexing/test_loc.py

+22
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,28 @@ def test_loc_setitem_consistency_slice_column_len(self):
690690
)
691691
tm.assert_series_equal(df[("Respondent", "Duration")], expected)
692692

693+
@pytest.mark.parametrize("unit", ["Y", "M", "D", "h", "m", "s", "ms", "us"])
694+
def test_loc_assign_non_ns_datetime(self, unit):
695+
# GH 27395, non-ns dtype assignment via .loc should work
696+
# and return the same result when using simple assignment
697+
df = DataFrame(
698+
{
699+
"timestamp": [
700+
np.datetime64("2017-02-11 12:41:29"),
701+
np.datetime64("1991-11-07 04:22:37"),
702+
]
703+
}
704+
)
705+
706+
df.loc[:, unit] = df.loc[:, "timestamp"].values.astype(
707+
"datetime64[{unit}]".format(unit=unit)
708+
)
709+
df["expected"] = df.loc[:, "timestamp"].values.astype(
710+
"datetime64[{unit}]".format(unit=unit)
711+
)
712+
expected = Series(df.loc[:, "expected"], name=unit)
713+
tm.assert_series_equal(df.loc[:, unit], expected)
714+
693715
def test_loc_setitem_frame(self):
694716
df = self.frame_labels
695717

0 commit comments

Comments
 (0)