Skip to content

Backport PR #53343: REF: Use np.result_type instead of np.find_common_type #53359

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
3 changes: 2 additions & 1 deletion pandas/core/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from pandas.core.dtypes.cast import (
construct_1d_object_array_from_listlike,
infer_dtype_from_array,
np_find_common_type,
)
from pandas.core.dtypes.common import (
ensure_float64,
Expand Down Expand Up @@ -522,7 +523,7 @@ def f(c, v):
f = np.in1d

else:
common = np.find_common_type([values.dtype, comps_array.dtype], [])
common = np_find_common_type(values.dtype, comps_array.dtype)
values = values.astype(common, copy=False)
comps_array = comps_array.astype(common, copy=False)
f = htable.ismember
Expand Down
6 changes: 4 additions & 2 deletions pandas/core/arrays/sparse/dtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@ def _subtype_with_str(self):
def _get_common_dtype(self, dtypes: list[DtypeObj]) -> DtypeObj | None:
# TODO for now only handle SparseDtypes and numpy dtypes => extend
# with other compatible extension dtypes
from pandas.core.dtypes.cast import np_find_common_type

if any(
isinstance(x, ExtensionDtype) and not isinstance(x, SparseDtype)
for x in dtypes
Expand All @@ -420,5 +422,5 @@ def _get_common_dtype(self, dtypes: list[DtypeObj]) -> DtypeObj | None:
stacklevel=find_stack_level(),
)

np_dtypes = [x.subtype if isinstance(x, SparseDtype) else x for x in dtypes]
return SparseDtype(np.find_common_type(np_dtypes, []), fill_value=fill_value)
np_dtypes = (x.subtype if isinstance(x, SparseDtype) else x for x in dtypes)
return SparseDtype(np_find_common_type(*np_dtypes), fill_value=fill_value)
28 changes: 27 additions & 1 deletion pandas/core/dtypes/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1368,6 +1368,32 @@ def common_dtype_categorical_compat(
return dtype


def np_find_common_type(*dtypes: np.dtype) -> np.dtype:
"""
np.find_common_type implementation pre-1.25 deprecation using np.result_type
https://github.com/pandas-dev/pandas/pull/49569#issuecomment-1308300065

Parameters
----------
dtypes : np.dtypes

Returns
-------
np.dtype
"""
try:
common_dtype = np.result_type(*dtypes)
if common_dtype.kind in "mMSU":
# NumPy promotion currently (1.25) misbehaves for for times and strings,
# so fall back to object (find_common_dtype did unless there
# was only one dtype)
common_dtype = np.dtype("O")

except TypeError:
common_dtype = np.dtype("O")
return common_dtype


@overload
def find_common_type(types: list[np.dtype]) -> np.dtype:
...
Expand Down Expand Up @@ -1435,7 +1461,7 @@ def find_common_type(types):
if is_integer_dtype(t) or is_float_dtype(t) or is_complex_dtype(t):
return np.dtype("object")

return np.find_common_type(types, [])
return np_find_common_type(*types)


def construct_2d_arraylike_from_scalar(
Expand Down
3 changes: 3 additions & 0 deletions pandas/core/dtypes/concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from pandas.core.dtypes.cast import (
common_dtype_categorical_compat,
find_common_type,
np_find_common_type,
)
from pandas.core.dtypes.common import is_dtype_equal
from pandas.core.dtypes.dtypes import (
Expand Down Expand Up @@ -110,6 +111,8 @@ def is_nonempty(x) -> bool:
# coerce to object
to_concat = [x.astype("object") for x in to_concat]
kinds = {"o"}
else:
target_dtype = np_find_common_type(*dtypes)

result = np.concatenate(to_concat, axis=axis)
if "b" in kinds and result.dtype.kind in ["i", "u", "f"]:
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/internals/concat.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from pandas.core.dtypes.cast import (
ensure_dtype_can_hold_na,
find_common_type,
np_find_common_type,
)
from pandas.core.dtypes.common import (
is_1d_only_ea_dtype,
Expand Down Expand Up @@ -144,7 +145,7 @@ def concat_arrays(to_concat: list) -> ArrayLike:
target_dtype = to_concat_no_proxy[0].dtype
elif all(x.kind in ["i", "u", "b"] and isinstance(x, np.dtype) for x in dtypes):
# GH#42092
target_dtype = np.find_common_type(list(dtypes), [])
target_dtype = np_find_common_type(*dtypes)
else:
target_dtype = find_common_type([arr.dtype for arr in to_concat_no_proxy])

Expand Down
4 changes: 1 addition & 3 deletions pandas/tests/dtypes/test_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -1012,9 +1012,7 @@ def test_maybe_convert_objects_itemsize(self, data0, data1):
data = [data0, data1]
arr = np.array(data, dtype="object")

common_kind = np.find_common_type(
[type(data0), type(data1)], scalar_types=[]
).kind
common_kind = np.result_type(type(data0), type(data1)).kind
kind0 = "python" if not hasattr(data0, "dtype") else data0.dtype.kind
kind1 = "python" if not hasattr(data1, "dtype") else data1.dtype.kind
if kind0 != "python" and kind1 != "python":
Expand Down