Skip to content

Commit 245e1a7

Browse files
Backport PR #51592 on branch 2.0.x (PERF: maybe_promote) (#51735)
Backport PR #51592: PERF: maybe_promote Co-authored-by: jbrockmendel <[email protected]>
1 parent 7e61e3a commit 245e1a7

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

pandas/core/dtypes/cast.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from pandas._libs.missing import (
2424
NA,
2525
NAType,
26+
checknull,
2627
)
2728
from pandas._libs.tslibs import (
2829
NaT,
@@ -556,6 +557,13 @@ def ensure_dtype_can_hold_na(dtype: DtypeObj) -> DtypeObj:
556557
return dtype
557558

558559

560+
_canonical_nans = {
561+
np.datetime64: np.datetime64("NaT", "ns"),
562+
np.timedelta64: np.timedelta64("NaT", "ns"),
563+
type(np.nan): np.nan,
564+
}
565+
566+
559567
def maybe_promote(dtype: np.dtype, fill_value=np.nan):
560568
"""
561569
Find the minimal dtype that can hold both the given dtype and fill_value.
@@ -577,18 +585,29 @@ def maybe_promote(dtype: np.dtype, fill_value=np.nan):
577585
ValueError
578586
If fill_value is a non-scalar and dtype is not object.
579587
"""
588+
orig = fill_value
589+
if checknull(fill_value):
590+
# https://github.com/pandas-dev/pandas/pull/39692#issuecomment-1441051740
591+
# avoid cache misses with NaN/NaT values that are not singletons
592+
fill_value = _canonical_nans.get(type(fill_value), fill_value)
593+
580594
# for performance, we are using a cached version of the actual implementation
581595
# of the function in _maybe_promote. However, this doesn't always work (in case
582596
# of non-hashable arguments), so we fallback to the actual implementation if needed
583597
try:
584598
# error: Argument 3 to "__call__" of "_lru_cache_wrapper" has incompatible type
585599
# "Type[Any]"; expected "Hashable" [arg-type]
586-
return _maybe_promote_cached(
600+
dtype, fill_value = _maybe_promote_cached(
587601
dtype, fill_value, type(fill_value) # type: ignore[arg-type]
588602
)
589603
except TypeError:
590604
# if fill_value is not hashable (required for caching)
591-
return _maybe_promote(dtype, fill_value)
605+
dtype, fill_value = _maybe_promote(dtype, fill_value)
606+
607+
if dtype == _dtype_obj and orig is not None:
608+
# GH#51592 restore our potentially non-canonical fill_value
609+
fill_value = orig
610+
return dtype, fill_value
592611

593612

594613
@functools.lru_cache(maxsize=128)

0 commit comments

Comments
 (0)