From 76fa77206aa042c3debba6255ed6aca0401da1b4 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 30 Jan 2022 12:50:46 -0800 Subject: [PATCH 1/3] BUG: Index[object].astype(td64) failing to raise with invalid NAs --- pandas/core/dtypes/astype.py | 10 ++++++---- pandas/tests/indexes/object/test_astype.py | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/pandas/core/dtypes/astype.py b/pandas/core/dtypes/astype.py index 7c7b7f3ba097f..11b147e207327 100644 --- a/pandas/core/dtypes/astype.py +++ b/pandas/core/dtypes/astype.py @@ -15,6 +15,7 @@ import numpy as np from pandas._libs import lib +from pandas._libs.tslibs.timedeltas import array_to_timedelta64 from pandas._typing import ( ArrayLike, DtypeObj, @@ -139,7 +140,7 @@ def astype_nansafe( elif is_object_dtype(arr.dtype): # work around NumPy brokenness, #1987 - if np.issubdtype(dtype.type, np.integer): + if dtype.kind in ["i", "u"]: return lib.astype_intsafe(arr, dtype) # if we have a datetime/timedelta array of objects @@ -154,9 +155,10 @@ def astype_nansafe( copy=copy, ) elif is_timedelta64_dtype(dtype): - from pandas import to_timedelta - - return astype_nansafe(to_timedelta(arr)._values, dtype, copy=copy) + # bc we know arr.dtype == object, this is equivalent to + # `np.asarray(to_timedelta(arr))`, but using a lower-level API that + # does not require a circular import. + return array_to_timedelta64(arr).view("m8[ns]").astype(dtype, copy=False) if dtype.name in ("datetime64", "timedelta64"): msg = ( diff --git a/pandas/tests/indexes/object/test_astype.py b/pandas/tests/indexes/object/test_astype.py index 9bfc0c1312200..9b33a78a49da3 100644 --- a/pandas/tests/indexes/object/test_astype.py +++ b/pandas/tests/indexes/object/test_astype.py @@ -1,4 +1,9 @@ -from pandas import Index +import pytest + +from pandas import ( + Index, + NaT, +) import pandas._testing as tm @@ -8,3 +13,12 @@ def test_astype_str_from_bytes(): result = idx.astype(str) expected = Index(["あ", "a"], dtype="object") tm.assert_index_equal(result, expected) + + +def test_astype_invalid_nas_to_tdt64_raises(): + # don't cast np.datetime64 NaTs to timedelta64 NaT + idx = Index([NaT.asm8] * 2, dtype=object) + + msg = r"Cannot cast Index to dtype timedelta64\[ns\]" + with pytest.raises(TypeError, match=msg): + idx.astype("m8[ns]") From bf03f875d281c4dda65f13a087c77cf903402d61 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 30 Jan 2022 12:52:35 -0800 Subject: [PATCH 2/3] whatsnew --- doc/source/whatsnew/v1.5.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 0f5b4a16d2f01..ed30dfe97a339 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -222,6 +222,7 @@ Datetimelike - Bug in :meth:`DataFrame.quantile` with datetime-like dtypes and no rows incorrectly returning ``float64`` dtype instead of retaining datetime-like dtype (:issue:`41544`) - Bug in :func:`to_datetime` with sequences of ``np.str_`` objects incorrectly raising (:issue:`32264`) - Bug in :class:`Timestamp` construction when passing datetime components as positional arguments and ``tzinfo`` as a keyword argument incorrectly raising (:issue:`31929`) +- Bug in :meth:`Index.astype` when casting from object dtype to ``timedelta64[ns]`` dtype incorrectly casting ``np.datetime64("NaT")`` values to ``np.timedelta64("NaT")`` instead of raising (:issue:`??`) - Timedelta From 1b1e91953e919b4575af6781401db897b4b37d08 Mon Sep 17 00:00:00 2001 From: Brock Date: Sun, 30 Jan 2022 12:53:33 -0800 Subject: [PATCH 3/3] GH refs --- doc/source/whatsnew/v1.5.0.rst | 2 +- pandas/tests/indexes/object/test_astype.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index ed30dfe97a339..2bb9905454e77 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -222,7 +222,7 @@ Datetimelike - Bug in :meth:`DataFrame.quantile` with datetime-like dtypes and no rows incorrectly returning ``float64`` dtype instead of retaining datetime-like dtype (:issue:`41544`) - Bug in :func:`to_datetime` with sequences of ``np.str_`` objects incorrectly raising (:issue:`32264`) - Bug in :class:`Timestamp` construction when passing datetime components as positional arguments and ``tzinfo`` as a keyword argument incorrectly raising (:issue:`31929`) -- Bug in :meth:`Index.astype` when casting from object dtype to ``timedelta64[ns]`` dtype incorrectly casting ``np.datetime64("NaT")`` values to ``np.timedelta64("NaT")`` instead of raising (:issue:`??`) +- Bug in :meth:`Index.astype` when casting from object dtype to ``timedelta64[ns]`` dtype incorrectly casting ``np.datetime64("NaT")`` values to ``np.timedelta64("NaT")`` instead of raising (:issue:`45722`) - Timedelta diff --git a/pandas/tests/indexes/object/test_astype.py b/pandas/tests/indexes/object/test_astype.py index 9b33a78a49da3..91e266e805868 100644 --- a/pandas/tests/indexes/object/test_astype.py +++ b/pandas/tests/indexes/object/test_astype.py @@ -16,7 +16,7 @@ def test_astype_str_from_bytes(): def test_astype_invalid_nas_to_tdt64_raises(): - # don't cast np.datetime64 NaTs to timedelta64 NaT + # GH#45722 don't cast np.datetime64 NaTs to timedelta64 NaT idx = Index([NaT.asm8] * 2, dtype=object) msg = r"Cannot cast Index to dtype timedelta64\[ns\]"