From f50252335cdf07d63b6cffd32ff98660e5be03bd Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 13 Apr 2023 07:16:08 -0700 Subject: [PATCH] PERF: avoid com.is_datetime_or_timedelta_dtype --- pandas/core/arrays/datetimelike.py | 6 +--- pandas/core/dtypes/common.py | 39 ------------------------ pandas/core/indexes/interval.py | 14 ++++++--- pandas/core/internals/construction.py | 3 +- pandas/core/reshape/tile.py | 3 +- pandas/core/tools/numeric.py | 3 +- pandas/tests/dtypes/cast/test_promote.py | 3 +- pandas/tests/dtypes/test_common.py | 14 --------- 8 files changed, 14 insertions(+), 71 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 658ffb4669c3c..2132a3dcbf292 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -84,7 +84,6 @@ from pandas.core.dtypes.common import ( is_all_strings, is_datetime64_any_dtype, - is_datetime_or_timedelta_dtype, is_dtype_equal, is_float_dtype, is_integer_dtype, @@ -474,10 +473,7 @@ def astype(self, dtype, copy: bool = True): if copy: values = values.copy() return values - elif ( - is_datetime_or_timedelta_dtype(dtype) - and not is_dtype_equal(self.dtype, dtype) - ) or is_float_dtype(dtype): + elif (dtype.kind in "mM" and self.dtype != dtype) or is_float_dtype(dtype): # disallow conversion between datetime/timedelta, # and conversions for any datetimelike to float msg = f"Cannot cast {type(self).__name__} to dtype {dtype}" diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py index 183fd5b2652b6..20d8cb4adc8b6 100644 --- a/pandas/core/dtypes/common.py +++ b/pandas/core/dtypes/common.py @@ -958,44 +958,6 @@ def is_timedelta64_ns_dtype(arr_or_dtype) -> bool: return _is_dtype(arr_or_dtype, lambda dtype: dtype == TD64NS_DTYPE) -def is_datetime_or_timedelta_dtype(arr_or_dtype) -> bool: - """ - Check whether the provided array or dtype is of - a timedelta64 or datetime64 dtype. - - Parameters - ---------- - arr_or_dtype : array-like or dtype - The array or dtype to check. - - Returns - ------- - boolean - Whether or not the array or dtype is of a timedelta64, - or datetime64 dtype. - - Examples - -------- - >>> is_datetime_or_timedelta_dtype(str) - False - >>> is_datetime_or_timedelta_dtype(int) - False - >>> is_datetime_or_timedelta_dtype(np.datetime64) - True - >>> is_datetime_or_timedelta_dtype(np.timedelta64) - True - >>> is_datetime_or_timedelta_dtype(np.array(['a', 'b'])) - False - >>> is_datetime_or_timedelta_dtype(pd.Series([1, 2])) - False - >>> is_datetime_or_timedelta_dtype(np.array([], dtype=np.timedelta64)) - True - >>> is_datetime_or_timedelta_dtype(np.array([], dtype=np.datetime64)) - True - """ - return _is_dtype_type(arr_or_dtype, classes(np.datetime64, np.timedelta64)) - - # This exists to silence numpy deprecation warnings, see GH#29553 def is_numeric_v_string_like(a: ArrayLike, b) -> bool: """ @@ -1693,7 +1655,6 @@ def is_all_strings(value: ArrayLike) -> bool: "is_datetime64_dtype", "is_datetime64_ns_dtype", "is_datetime64tz_dtype", - "is_datetime_or_timedelta_dtype", "is_decimal", "is_dict_like", "is_dtype_equal", diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 8cf5151a8f0b5..ca01b1fd5fe6f 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -43,7 +43,6 @@ ) from pandas.core.dtypes.common import ( ensure_platform_int, - is_datetime_or_timedelta_dtype, is_dtype_equal, is_float, is_float_dtype, @@ -53,6 +52,7 @@ is_number, is_object_dtype, is_scalar, + pandas_dtype, ) from pandas.core.dtypes.dtypes import ( DatetimeTZDtype, @@ -115,8 +115,10 @@ def _get_next_label(label): dtype = getattr(label, "dtype", type(label)) if isinstance(label, (Timestamp, Timedelta)): - dtype = "datetime64" - if is_datetime_or_timedelta_dtype(dtype) or isinstance(dtype, DatetimeTZDtype): + dtype = "datetime64[ns]" + dtype = pandas_dtype(dtype) + + if lib.is_np_dtype(dtype, "mM") or isinstance(dtype, DatetimeTZDtype): return label + np.timedelta64(1, "ns") elif is_integer_dtype(dtype): return label + 1 @@ -129,8 +131,10 @@ def _get_next_label(label): def _get_prev_label(label): dtype = getattr(label, "dtype", type(label)) if isinstance(label, (Timestamp, Timedelta)): - dtype = "datetime64" - if is_datetime_or_timedelta_dtype(dtype) or isinstance(dtype, DatetimeTZDtype): + dtype = "datetime64[ns]" + dtype = pandas_dtype(dtype) + + if lib.is_np_dtype(dtype, "mM") or isinstance(dtype, DatetimeTZDtype): return label - np.timedelta64(1, "ns") elif is_integer_dtype(dtype): return label - 1 diff --git a/pandas/core/internals/construction.py b/pandas/core/internals/construction.py index c8fef14db9341..38cf8582aa79d 100644 --- a/pandas/core/internals/construction.py +++ b/pandas/core/internals/construction.py @@ -28,7 +28,6 @@ from pandas.core.dtypes.common import ( is_1d_only_ea_dtype, is_bool_dtype, - is_datetime_or_timedelta_dtype, is_dtype_equal, is_float_dtype, is_integer_dtype, @@ -349,7 +348,7 @@ def ndarray_to_mgr( for i in range(values.shape[1]) ] else: - if is_datetime_or_timedelta_dtype(values.dtype): + if lib.is_np_dtype(values.dtype, "mM"): values = ensure_wrapped_if_datetimelike(values) arrays = [values[:, i] for i in range(values.shape[1])] diff --git a/pandas/core/reshape/tile.py b/pandas/core/reshape/tile.py index f3f2f41491e87..4fd3533662eea 100644 --- a/pandas/core/reshape/tile.py +++ b/pandas/core/reshape/tile.py @@ -24,7 +24,6 @@ ensure_platform_int, is_bool_dtype, is_datetime64_dtype, - is_datetime_or_timedelta_dtype, is_integer, is_list_like, is_numeric_dtype, @@ -561,7 +560,7 @@ def _convert_bin_to_datelike_type(bins, dtype: DtypeObj | None): """ if isinstance(dtype, DatetimeTZDtype): bins = to_datetime(bins.astype(np.int64), utc=True).tz_convert(dtype.tz) - elif is_datetime_or_timedelta_dtype(dtype): + elif lib.is_np_dtype(dtype, "mM"): bins = Index(bins.astype(np.int64), dtype=dtype) return bins diff --git a/pandas/core/tools/numeric.py b/pandas/core/tools/numeric.py index a06152272797f..b9a5c431d8387 100644 --- a/pandas/core/tools/numeric.py +++ b/pandas/core/tools/numeric.py @@ -14,7 +14,6 @@ from pandas.core.dtypes.common import ( ensure_object, is_bool_dtype, - is_datetime_or_timedelta_dtype, is_decimal, is_integer_dtype, is_number, @@ -213,7 +212,7 @@ def to_numeric( new_mask: np.ndarray | None = None if is_numeric_dtype(values_dtype): pass - elif is_datetime_or_timedelta_dtype(values_dtype): + elif lib.is_np_dtype(values_dtype, "mM"): values = values.view(np.int64) else: values = ensure_object(values) diff --git a/pandas/tests/dtypes/cast/test_promote.py b/pandas/tests/dtypes/cast/test_promote.py index 33019269aa3b7..a3ed5fcf139da 100644 --- a/pandas/tests/dtypes/cast/test_promote.py +++ b/pandas/tests/dtypes/cast/test_promote.py @@ -14,7 +14,6 @@ from pandas.core.dtypes.common import ( is_complex_dtype, is_datetime64_dtype, - is_datetime_or_timedelta_dtype, is_float_dtype, is_integer_dtype, is_object_dtype, @@ -516,7 +515,7 @@ def test_maybe_promote_any_numpy_dtype_with_na(any_numpy_dtype, nulls_fixture): # but *does* cast None to np.nan expected_dtype = np.dtype(object) exp_val_for_scalar = fill_value - elif is_datetime_or_timedelta_dtype(dtype): + elif dtype.kind in "mM": # datetime / timedelta cast all missing values to dtyped-NaT expected_dtype = dtype exp_val_for_scalar = dtype.type("NaT", "ns") diff --git a/pandas/tests/dtypes/test_common.py b/pandas/tests/dtypes/test_common.py index 2c7651e0489d8..a28a5b62f4ad0 100644 --- a/pandas/tests/dtypes/test_common.py +++ b/pandas/tests/dtypes/test_common.py @@ -512,20 +512,6 @@ def test_is_timedelta64_ns_dtype(): assert com.is_timedelta64_ns_dtype(np.array([1, 2], dtype="m8[ns]")) -def test_is_datetime_or_timedelta_dtype(): - assert not com.is_datetime_or_timedelta_dtype(int) - assert not com.is_datetime_or_timedelta_dtype(str) - assert not com.is_datetime_or_timedelta_dtype(pd.Series([1, 2])) - assert not com.is_datetime_or_timedelta_dtype(np.array(["a", "b"])) - - assert not com.is_datetime_or_timedelta_dtype(DatetimeTZDtype("ns", "US/Eastern")) - - assert com.is_datetime_or_timedelta_dtype(np.datetime64) - assert com.is_datetime_or_timedelta_dtype(np.timedelta64) - assert com.is_datetime_or_timedelta_dtype(np.array([], dtype=np.timedelta64)) - assert com.is_datetime_or_timedelta_dtype(np.array([], dtype=np.datetime64)) - - def test_is_numeric_v_string_like(): assert not com.is_numeric_v_string_like(np.array([1]), 1) assert not com.is_numeric_v_string_like(np.array([1]), np.array([2]))