From c98667c47c3bc56b1e13116c30133d1ec7b69ea2 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Tue, 22 May 2018 07:26:39 -0400 Subject: [PATCH] cross type arithmetic --- pandas/core/arrays/integer.py | 9 +++++++-- .../tests/extension/integer/test_integer.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/integer.py b/pandas/core/arrays/integer.py index 5b92e1bb6f2f05..1a2a10f2b2de22 100644 --- a/pandas/core/arrays/integer.py +++ b/pandas/core/arrays/integer.py @@ -112,6 +112,7 @@ def coerce_to_array(values, dtype, mask=None, copy=False): 'mixed-integer', 'mixed-integer-float']: raise TypeError("{} cannot be converted to an IntegerDtype".format( values.dtype)) + elif not (is_integer_dtype(values) or is_float_dtype(values)): raise TypeError("{} cannot be converted to an IntegerDtype".format( values.dtype)) @@ -126,15 +127,19 @@ def coerce_to_array(values, dtype, mask=None, copy=False): if not mask.ndim == 1: raise TypeError("mask must be a 1D list-like") + # avoid float->int numpy conversion issues + if is_object_dtype(values): + mask |= isna(values) + + # we copy as need to coerce here if mask.any(): - # we copy as need to coerce here values = values.copy() values[mask] = 1 values = values.astype(dtype.type) - else: values = values.astype(dtype.type, copy=False) + return values, mask diff --git a/pandas/tests/extension/integer/test_integer.py b/pandas/tests/extension/integer/test_integer.py index 31b1a98b14d2e0..254056d00d447d 100644 --- a/pandas/tests/extension/integer/test_integer.py +++ b/pandas/tests/extension/integer/test_integer.py @@ -393,3 +393,22 @@ def test_to_integer_array(values, expected): # convert existing arrays to IntegerArrays result = to_integer_array(values) tm.assert_extension_array_equal(result, expected) + + +def test_cross_type_arithmetic(): + + df = pd.DataFrame({'A': pd.Series([1, 2, np.nan], dtype='Int64'), + 'B': pd.Series([1, np.nan, 3], dtype='UInt8'), + 'C': [1, 2, 3]}) + + result = df.A + df.C + expected = pd.Series([2, 4, np.nan], dtype='Int64') + tm.assert_series_equal(result, expected) + + result = (df.A + df.C) * 3 == 12 + expected = pd.Series([False, True, False]) + tm.assert_series_equal(result, expected) + + result = df.A + df.B + expected = pd.Series([2, np.nan, np.nan], dtype='Int64') + tm.assert_series_equal(result, expected)