diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 29009c1627cfb..d312612cdc680 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -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, @@ -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 diff --git a/pandas/core/arrays/sparse/dtype.py b/pandas/core/arrays/sparse/dtype.py index c7a44d3606fa6..185ed2911c11e 100644 --- a/pandas/core/arrays/sparse/dtype.py +++ b/pandas/core/arrays/sparse/dtype.py @@ -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 @@ -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) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 05e108099fd5a..156c7c67c7011 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -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: ... @@ -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( diff --git a/pandas/core/dtypes/concat.py b/pandas/core/dtypes/concat.py index 28bc849088d5f..709563020778e 100644 --- a/pandas/core/dtypes/concat.py +++ b/pandas/core/dtypes/concat.py @@ -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 ( @@ -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"]: diff --git a/pandas/core/internals/concat.py b/pandas/core/internals/concat.py index a33ce8fd5c459..e9cf7a151b627 100644 --- a/pandas/core/internals/concat.py +++ b/pandas/core/internals/concat.py @@ -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, @@ -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]) diff --git a/pandas/tests/dtypes/test_inference.py b/pandas/tests/dtypes/test_inference.py index 650eb033dcd9e..a65fa240bf7f3 100644 --- a/pandas/tests/dtypes/test_inference.py +++ b/pandas/tests/dtypes/test_inference.py @@ -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":