diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 0ecdde89d9013..54c7a8697e23f 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -562,6 +562,7 @@ Removal of prior version deprecations/changes - Changed behavior of :meth:`SparseArray.astype` when given a dtype that is not explicitly ``SparseDtype``, cast to the exact requested dtype rather than silently using a ``SparseDtype`` instead (:issue:`34457`) - Changed behavior of :meth:`Index.ravel` to return a view on the original :class:`Index` instead of a ``np.ndarray`` (:issue:`36900`) - Changed behavior of :meth:`Series.to_frame` and :meth:`Index.to_frame` with explicit ``name=None`` to use ``None`` for the column name instead of the index's name or default ``0`` (:issue:`45523`) +- Changed behavior of :func:`concat` with one array of ``bool``-dtype and another of integer dtype, this now returns ``object`` dtype instead of integer dtype; explicitly cast the bool object to integer before concatenating to get the old behavior (:issue:`45101`) - Changed behavior of :class:`DataFrame` constructor given floating-point ``data`` and an integer ``dtype``, when the data cannot be cast losslessly, the floating point dtype is retained, matching :class:`Series` behavior (:issue:`41170`) - Changed behavior of :class:`Index` constructor when given a ``np.ndarray`` with object-dtype containing numeric entries; this now retains object dtype rather than inferring a numeric dtype, consistent with :class:`Series` behavior (:issue:`42870`) - Changed behavior of :meth:`Index.__and__`, :meth:`Index.__or__` and :meth:`Index.__xor__` to behave as logical operations (matching :class:`Series` behavior) instead of aliases for set operations (:issue:`37374`) diff --git a/pandas/core/dtypes/concat.py b/pandas/core/dtypes/concat.py index 03429fd9fee1d..80eaf13d9dd06 100644 --- a/pandas/core/dtypes/concat.py +++ b/pandas/core/dtypes/concat.py @@ -4,12 +4,10 @@ from __future__ import annotations from typing import TYPE_CHECKING -import warnings import numpy as np from pandas._typing import AxisInt -from pandas.util._exceptions import find_stack_level from pandas.core.dtypes.astype import astype_array from pandas.core.dtypes.cast import ( @@ -115,15 +113,8 @@ def is_nonempty(x) -> bool: result = np.concatenate(to_concat, axis=axis) if "b" in kinds and result.dtype.kind in ["i", "u", "f"]: - # GH#39817 - warnings.warn( - "Behavior when concatenating bool-dtype and numeric-dtype arrays is " - "deprecated; in a future version these will cast to object dtype " - "(instead of coercing bools to numeric values). To retain the old " - "behavior, explicitly cast bool-dtype arrays to numeric dtype.", - FutureWarning, - stacklevel=find_stack_level(), - ) + # GH#39817 cast to object instead of casting bools to numeric + result = result.astype(object, copy=False) return result diff --git a/pandas/tests/reshape/concat/test_empty.py b/pandas/tests/reshape/concat/test_empty.py index 18c0645df1ceb..68220855b3d7a 100644 --- a/pandas/tests/reshape/concat/test_empty.py +++ b/pandas/tests/reshape/concat/test_empty.py @@ -96,7 +96,7 @@ def test_concat_empty_series_timelike(self, tz, values): "left,right,expected", [ # booleans - (np.bool_, np.int32, np.int32), + (np.bool_, np.int32, np.object_), # changed from int32 in 2.0 GH#39817 (np.bool_, np.float32, np.object_), # datetime-like ("m8[ns]", np.bool_, np.object_), @@ -109,12 +109,8 @@ def test_concat_empty_series_timelike(self, tz, values): ], ) def test_concat_empty_series_dtypes(self, left, right, expected): - warn = None - if (left is np.bool_ or right is np.bool_) and expected is not np.object_: - warn = FutureWarning - with tm.assert_produces_warning(warn, match="concatenating bool-dtype"): - # GH#39817 - result = concat([Series(dtype=left), Series(dtype=right)]) + # GH#39817, GH#45101 + result = concat([Series(dtype=left), Series(dtype=right)]) assert result.dtype == expected @pytest.mark.parametrize(