Skip to content

Commit 8578696

Browse files
authored
BUG: concat of bool and boolean giving object dtype (#43409)
1 parent 3f1a616 commit 8578696

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

doc/source/whatsnew/v1.4.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ Reshaping
419419
- :func:`concat` creating :class:`MultiIndex` with duplicate level entries when concatenating a :class:`DataFrame` with duplicates in :class:`Index` and multiple keys (:issue:`42651`)
420420
- Bug in :meth:`pandas.cut` on :class:`Series` with duplicate indices (:issue:`42185`) and non-exact :meth:`pandas.CategoricalIndex` (:issue:`42425`)
421421
- Bug in :meth:`DataFrame.append` failing to retain dtypes when appended columns do not match (:issue:`43392`)
422+
- Bug in :func:`concat` of ``bool`` and ``boolean`` dtypes resulting in ``object`` dtype instead of ``boolean`` dtype (:issue:`42800`)
422423
-
423424

424425
Sparse

pandas/core/arrays/boolean.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
ArrayLike,
1818
AstypeArg,
1919
Dtype,
20+
DtypeObj,
2021
npt,
2122
type_t,
2223
)
@@ -153,6 +154,18 @@ def __from_arrow__(
153154
else:
154155
return BooleanArray._concat_same_type(results)
155156

157+
def _get_common_dtype(self, dtypes: list[DtypeObj]) -> DtypeObj | None:
158+
# Handle only boolean + np.bool_ -> boolean, since other cases like
159+
# Int64 + boolean -> Int64 will be handled by the other type
160+
if all(
161+
isinstance(t, BooleanDtype)
162+
or (isinstance(t, np.dtype) and (np.issubdtype(t, np.bool_)))
163+
for t in dtypes
164+
):
165+
return BooleanDtype()
166+
else:
167+
return None
168+
156169

157170
def coerce_to_array(
158171
values, mask=None, copy: bool = False

pandas/tests/reshape/concat/test_concat.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,24 @@ def test_concat_preserves_extension_int64_dtype():
597597
tm.assert_frame_equal(result, expected)
598598

599599

600+
@pytest.mark.parametrize(
601+
"dtype1,dtype2,expected_dtype",
602+
[
603+
("bool", "bool", "bool"),
604+
("boolean", "bool", "boolean"),
605+
("bool", "boolean", "boolean"),
606+
("boolean", "boolean", "boolean"),
607+
],
608+
)
609+
def test_concat_bool_types(dtype1, dtype2, expected_dtype):
610+
# GH 42800
611+
ser1 = Series([True, False], dtype=dtype1)
612+
ser2 = Series([False, True], dtype=dtype2)
613+
result = concat([ser1, ser2], ignore_index=True)
614+
expected = Series([True, False, False, True], dtype=expected_dtype)
615+
tm.assert_series_equal(result, expected)
616+
617+
600618
@pytest.mark.parametrize(
601619
("keys", "integrity"),
602620
[

0 commit comments

Comments
 (0)