Skip to content

PERF: avoid com.is_datetime_or_timedelta_dtype #52649

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
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
6 changes: 1 addition & 5 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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}"
Expand Down
39 changes: 0 additions & 39 deletions pandas/core/dtypes/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
"""
Expand Down Expand Up @@ -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",
Expand Down
14 changes: 9 additions & 5 deletions pandas/core/indexes/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -53,6 +52,7 @@
is_number,
is_object_dtype,
is_scalar,
pandas_dtype,
)
from pandas.core.dtypes.dtypes import (
DatetimeTZDtype,
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 1 addition & 2 deletions pandas/core/internals/construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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])]

Expand Down
3 changes: 1 addition & 2 deletions pandas/core/reshape/tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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

Expand Down
3 changes: 1 addition & 2 deletions pandas/core/tools/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions pandas/tests/dtypes/cast/test_promote.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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")
Expand Down
14 changes: 0 additions & 14 deletions pandas/tests/dtypes/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down