Skip to content
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.22.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Conversion
^^^^^^^^^^

- Bug in :class:`Index` constructor with `dtype='uint64'` where int-like floats were not coerced to :class:`UInt64Index` (:issue:`18400`)
-
- Bug in :class:`Block` where math operations on a `DataFrame` containing `bool` as elements are coerced to `bool` in :meth:`coerce_to_target_dtype`.
-

Indexing
Expand Down
10 changes: 6 additions & 4 deletions pandas/core/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ def f(m, v, i):

return [self.make_block(new_values, fastpath=True)]

def coerce_to_target_dtype(self, other):
def coerce_to_target_dtype(self, other, force_coericion=False):
"""
coerce the current block to a dtype compat for other
we will return a block, possibly object, and not raise
Expand All @@ -1042,8 +1042,10 @@ def coerce_to_target_dtype(self, other):
return self

if self.is_bool or is_object_dtype(dtype) or is_bool_dtype(dtype):
# we don't upcast to bool
return self.astype(object)
if force_coericion and is_float_dtype(dtype) or is_integer_dtype(dtype):
return self.astype(dtype)
else:
return self.astype(object)

elif ((self.is_float or self.is_complex) and
(is_integer_dtype(dtype) or is_float_dtype(dtype))):
Expand Down Expand Up @@ -1324,7 +1326,7 @@ def eval(self, func, other, errors='raise', try_cast=False, mgr=None):
values, values_mask, other, other_mask = self._try_coerce_args(
transf(values), other)
except TypeError:
block = self.coerce_to_target_dtype(orig_other)
block = self.coerce_to_target_dtype(orig_other, True)
return block.eval(func, orig_other,
errors=errors,
try_cast=try_cast, mgr=mgr)
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/frame/test_dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,19 @@ def test_arg_for_errors_in_astype(self):

df.astype(np.int8, errors='ignore')

from operator import (add, mul, floordiv, sub)

@pytest.mark.parametrize("num", [1.0, 1])
@pytest.mark.parametrize("struct", [pd.Series, pd.DataFrame])
@pytest.mark.parametrize('op', [add, mul, floordiv, sub])
def test_assert_list_and_bool_coerce(self, num, struct, op):
# issue 18549
target_type = np.array([op(num, num)]).dtype
res = op(struct([True]), num).dtypes
if isinstance(res, pd.Series):
res = res[0]
assert target_type == res


class TestDataFrameDatetimeWithTZ(TestData):

Expand Down