Skip to content

Commit d5c6cfb

Browse files
committed
Move all-NA handling logic to maybe_convert_objects
1 parent 242dbdf commit d5c6cfb

File tree

3 files changed

+19
-3
lines changed

3 files changed

+19
-3
lines changed

pandas/_libs/lib.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def maybe_convert_objects(
9494
convert_numeric: bool = ...,
9595
convert_non_numeric: Literal[False] = ...,
9696
convert_to_nullable_dtype: Literal[False] = ...,
97+
dtype_if_all_na: DtypeObj | None = ...,
9798
dtype_if_all_nat: DtypeObj | None = ...,
9899
) -> npt.NDArray[np.object_ | np.number]: ...
99100
@overload
@@ -105,6 +106,7 @@ def maybe_convert_objects(
105106
convert_numeric: bool = ...,
106107
convert_non_numeric: bool = ...,
107108
convert_to_nullable_dtype: Literal[True] = ...,
109+
dtype_if_all_na: DtypeObj | None = ...,
108110
dtype_if_all_nat: DtypeObj | None = ...,
109111
) -> ArrayLike: ...
110112
@overload
@@ -116,6 +118,7 @@ def maybe_convert_objects(
116118
convert_numeric: bool = ...,
117119
convert_non_numeric: bool = ...,
118120
convert_to_nullable_dtype: bool = ...,
121+
dtype_if_all_na: DtypeObj | None = ...,
119122
dtype_if_all_nat: DtypeObj | None = ...,
120123
) -> ArrayLike: ...
121124
@overload

pandas/_libs/lib.pyx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,6 +2545,7 @@ def maybe_convert_objects(ndarray[object] objects,
25452545
bint convert_numeric=True, # NB: different default!
25462546
bint convert_to_nullable_dtype=False,
25472547
bint convert_non_numeric=False,
2548+
object dtype_if_all_na=None,
25482549
object dtype_if_all_nat=None) -> "ArrayLike":
25492550
"""
25502551
Type inference function-- convert object array to proper dtype
@@ -2566,6 +2567,8 @@ def maybe_convert_objects(ndarray[object] objects,
25662567
encountered, whether to convert and return an Boolean/IntegerArray.
25672568
convert_non_numeric : bool, default False
25682569
Whether to convert datetime, timedelta, period, interval types.
2570+
dtype_if_all_na : np.dtype, ExtensionDtype, or None, default None
2571+
Dtype to cast to if we have all-NA or all-None.
25692572
dtype_if_all_nat : np.dtype, ExtensionDtype, or None, default None
25702573
Dtype to cast to if we have all-NaT.
25712574

@@ -2838,6 +2841,16 @@ def maybe_convert_objects(ndarray[object] objects,
28382841
else:
28392842
seen.object_ = True
28402843

2844+
elif seen.null_:
2845+
if not seen.object_ and not seen.numeric_ and not seen.bool_:
2846+
# all NaT, None, or nan (at least one NA or None)
2847+
dtype = dtype_if_all_na
2848+
if dtype is not None:
2849+
cls = dtype.construct_array_type()
2850+
obj = cls._from_sequence([], dtype=dtype)
2851+
taker = -np.ones((<object>objects).shape, dtype=np.intp)
2852+
return obj.take(taker, allow_fill=True)
2853+
28412854
if not convert_numeric:
28422855
# Note: we count "bool" as numeric here. This is because
28432856
# np.array(list_of_items) will convert bools just like it will numeric

pandas/core/arrays/masked.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,10 @@ def _from_sequence(cls, scalars, *, dtype=None, copy: bool = False) -> Self:
149149
return cls(values, mask)
150150

151151
def _cast_pointwise_result(self, values) -> ArrayLike:
152-
if isna(values).all():
153-
return type(self)._from_sequence(values, dtype=self.dtype)
154152
values = np.asarray(values, dtype=object)
155-
result = lib.maybe_convert_objects(values, convert_to_nullable_dtype=True)
153+
result = lib.maybe_convert_objects(
154+
values, convert_to_nullable_dtype=True, dtype_if_all_na=self.dtype
155+
)
156156
lkind = self.dtype.kind
157157
rkind = result.dtype.kind
158158
if (lkind in "iu" and rkind in "iu") or (lkind == rkind == "f"):

0 commit comments

Comments
 (0)