Skip to content

Commit 90c00c3

Browse files
committed
BUG: permit str dtype -> IntegerDtype conversions
Resolves pandas-dev#25472, resolves pandas-dev#25288.
1 parent 1d5899d commit 90c00c3

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

pandas/core/arrays/integer.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
is_integer_dtype,
3333
is_list_like,
3434
is_object_dtype,
35+
is_string_dtype,
3536
pandas_dtype,
3637
)
3738
from pandas.core.dtypes.missing import isna
@@ -124,12 +125,15 @@ def safe_cast(values, dtype, copy: bool):
124125
Safely cast the values to the dtype if they
125126
are equivalent, meaning floats must be equivalent to the
126127
ints.
127-
128128
"""
129+
if is_string_dtype(values):
130+
# casts from str are always safe since they raise
131+
# a ValueError if the str cannot be parsed into an int
132+
return values.astype(dtype, copy=copy)
133+
129134
try:
130135
return values.astype(dtype, casting="safe", copy=copy)
131136
except TypeError as err:
132-
133137
casted = values.astype(dtype, copy=copy)
134138
if (casted == values).all():
135139
return casted
@@ -143,7 +147,7 @@ def coerce_to_array(
143147
values, dtype, mask=None, copy: bool = False
144148
) -> tuple[np.ndarray, np.ndarray]:
145149
"""
146-
Coerce the input values array to numpy arrays with a mask
150+
Coerce the input values array to numpy arrays with a mask.
147151
148152
Parameters
149153
----------
@@ -204,7 +208,9 @@ def coerce_to_array(
204208
elif is_bool_dtype(values) and is_integer_dtype(dtype):
205209
values = np.array(values, dtype=int, copy=copy)
206210

207-
elif not (is_integer_dtype(values) or is_float_dtype(values)):
211+
elif not (
212+
is_integer_dtype(values) or is_float_dtype(values) or is_string_dtype(values)
213+
):
208214
raise TypeError(f"{values.dtype} cannot be converted to an IntegerDtype")
209215

210216
if mask is None:
@@ -230,9 +236,7 @@ def coerce_to_array(
230236
if mask.any():
231237
values = values.copy()
232238
values[mask] = 1
233-
values = safe_cast(values, dtype, copy=False)
234-
else:
235-
values = safe_cast(values, dtype, copy=False)
239+
values = safe_cast(values, dtype, copy=False)
236240

237241
return values, mask
238242

pandas/core/dtypes/common.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,14 @@ def ensure_python_int(value: int | np.integer) -> int:
144144

145145

146146
def classes(*klasses) -> Callable:
147-
"""evaluate if the tipo is a subclass of the klasses"""
147+
"""Evaluate if the tipo is a subclass of the klasses."""
148148
return lambda tipo: issubclass(tipo, klasses)
149149

150150

151151
def classes_and_not_datetimelike(*klasses) -> Callable:
152152
"""
153-
evaluate if the tipo is a subclass of the klasses
154-
and not a datetimelike
153+
Evaluate if the tipo is a subclass of the klasses
154+
and not a datetimelike.
155155
"""
156156
return lambda tipo: (
157157
issubclass(tipo, klasses)
@@ -679,7 +679,7 @@ def is_integer_dtype(arr_or_dtype) -> bool:
679679
"""
680680
Check whether the provided array or dtype is of an integer dtype.
681681
682-
Unlike in `in_any_int_dtype`, timedelta64 instances will return False.
682+
Unlike in `is_any_int_dtype`, timedelta64 instances will return False.
683683
684684
The nullable Integer dtypes (e.g. pandas.Int64Dtype) are also considered
685685
as integer by this function.
@@ -731,7 +731,7 @@ def is_signed_integer_dtype(arr_or_dtype) -> bool:
731731
"""
732732
Check whether the provided array or dtype is of a signed integer dtype.
733733
734-
Unlike in `in_any_int_dtype`, timedelta64 instances will return False.
734+
Unlike in `is_any_int_dtype`, timedelta64 instances will return False.
735735
736736
The nullable Integer dtypes (e.g. pandas.Int64Dtype) are also considered
737737
as integer by this function.
@@ -1525,7 +1525,7 @@ def is_complex_dtype(arr_or_dtype) -> bool:
15251525

15261526
def _is_dtype(arr_or_dtype, condition) -> bool:
15271527
"""
1528-
Return a boolean if the condition is satisfied for the arr_or_dtype.
1528+
Return true if the condition is satisfied for the arr_or_dtype.
15291529
15301530
Parameters
15311531
----------
@@ -1584,7 +1584,7 @@ def get_dtype(arr_or_dtype) -> DtypeObj:
15841584

15851585
def _is_dtype_type(arr_or_dtype, condition) -> bool:
15861586
"""
1587-
Return a boolean if the condition is satisfied for the arr_or_dtype.
1587+
Return true if the condition is satisfied for the arr_or_dtype.
15881588
15891589
Parameters
15901590
----------

0 commit comments

Comments
 (0)