diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 304eeac87f64d..b34f25267184a 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -357,6 +357,26 @@ def maybe_promote(dtype, fill_value=np.nan): fill_value = np.nan dtype = np.dtype(np.object_) + return maybe_promote_scalar(dtype, fill_value) + + +def maybe_promote_scalar(dtype, fill_value=np.nan): + """ + Find the minimal dtype that can hold both the given dtype and fill_value. + + Parameters + ---------- + dtype : np.dtype or ExceptionDtype + fill_value : scalar, default np.nan + + Returns + ------- + dtype + Upcasted from dtype argument if necessary. + fill_value + Upcasted from fill_value argument if necessary. + """ + # returns tuple of (dtype, fill_value) if issubclass(dtype.type, np.datetime64): if isinstance(fill_value, datetime) and fill_value.tzinfo is not None: diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 51108d9a5a573..b494aab9dda27 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -22,7 +22,7 @@ maybe_downcast_numeric, maybe_downcast_to_dtype, maybe_infer_dtype_type, - maybe_promote, + maybe_promote_scalar, maybe_upcast, soft_convert_objects, ) @@ -856,7 +856,7 @@ def setitem(self, indexer, value): # cast the values to a type that can hold nan (if necessary) if not self._can_hold_element(value): - dtype, _ = maybe_promote(arr_value.dtype) + dtype, _ = maybe_promote_scalar(arr_value.dtype) values = values.astype(dtype) if transpose: @@ -994,7 +994,7 @@ def f(mask, val, idx): n = np.array(new) # type of the new block - dtype, _ = maybe_promote(n.dtype) + dtype, _ = maybe_promote_scalar(n.dtype) # we need to explicitly astype here to make a copy n = n.astype(dtype) @@ -3169,7 +3169,7 @@ def _putmask_preserve(nv, n): return _putmask_preserve(v, n) # change the dtype if needed - dtype, _ = maybe_promote(n.dtype) + dtype, _ = maybe_promote_scalar(n.dtype) if is_extension_type(v.dtype) and is_object_dtype(dtype): v = v._internal_get_values(dtype) diff --git a/pandas/core/internals/managers.py b/pandas/core/internals/managers.py index 21ae820cfcee6..c18ba590ab719 100644 --- a/pandas/core/internals/managers.py +++ b/pandas/core/internals/managers.py @@ -14,7 +14,7 @@ find_common_type, infer_dtype_from_scalar, maybe_convert_objects, - maybe_promote, + maybe_promote_scalar, ) from pandas.core.dtypes.common import ( _NS_DTYPE, @@ -1291,7 +1291,7 @@ def _slice_take_blocks_ax0(self, slice_or_indexer, fill_tuple=None): return [blk.getitem_block(slobj, new_mgr_locs=slice(0, sllen))] elif not allow_fill or self.ndim == 1: if allow_fill and fill_tuple[0] is None: - _, fill_value = maybe_promote(blk.dtype) + _, fill_value = maybe_promote_scalar(blk.dtype) fill_tuple = (fill_value,) return [