diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 0173807cb9bd0..0e78e230f8ee4 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -154,7 +154,7 @@ Indexing ^^^^^^^^ - Bug in :meth:`DataFrame.iloc` where indexing a single row on a :class:`DataFrame` with a single ExtensionDtype column gave a copy instead of a view on the underlying data (:issue:`45241`) - Bug in :meth:`Series.__setitem__` with a non-integer :class:`Index` when using an integer key to set a value that cannot be set inplace where a ``ValueError`` was raised insead of casting to a common dtype (:issue:`45070`) -- Bug when setting an integer too large for a :class:`Series` dtype failing to coerce to a common type (:issue:`26049`) +- Bug when setting a value too large for a :class:`Series` dtype failing to coerce to a common type (:issue:`26049`, :issue:`32878`) - Missing diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index d51f878a1c85a..1047363779ac8 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -1931,12 +1931,21 @@ def np_can_hold_element(dtype: np.dtype, element: Any) -> Any: raise ValueError elif dtype.kind == "c": + if lib.is_integer(element) or lib.is_complex(element) or lib.is_float(element): + if np.isnan(element): + # see test_where_complex GH#6345 + return dtype.type(element) + + casted = dtype.type(element) + if casted == element: + return casted + # otherwise e.g. overflow see test_32878_complex_itemsize + raise ValueError + if tipo is not None: if tipo.kind in ["c", "f", "i", "u"]: return element raise ValueError - if lib.is_integer(element) or lib.is_complex(element) or lib.is_float(element): - return element raise ValueError elif dtype.kind == "b": diff --git a/pandas/tests/series/indexing/test_setitem.py b/pandas/tests/series/indexing/test_setitem.py index d4b69abb6aba9..2a41b77b98ca0 100644 --- a/pandas/tests/series/indexing/test_setitem.py +++ b/pandas/tests/series/indexing/test_setitem.py @@ -1373,6 +1373,19 @@ def test_32878_int_itemsize(): tm.assert_series_equal(ser, expected) +def test_32878_complex_itemsize(): + arr = np.arange(5).astype("c8") + ser = Series(arr) + val = np.finfo(np.float64).max + val = val.astype("c16") + + # GH#32878 used to coerce val to inf+0.000000e+00j + ser[0] = val + assert ser[0] == val + expected = Series([val, 1, 2, 3, 4], dtype="c16") + tm.assert_series_equal(ser, expected) + + def test_37692(indexer_al): # GH#37692 ser = Series([1, 2, 3], index=["a", "b", "c"]) @@ -1424,21 +1437,6 @@ def test_setitem_positional_float_into_int_coerces(): tm.assert_series_equal(ser, expected) -@pytest.mark.xfail(reason="Fails to upcast") -def test_32878_complex_itemsize(): - # TODO: when fixed, put adjacent to test_32878_int_itemsize - arr = np.arange(5).astype("c8") - ser = Series(arr) - val = np.finfo(np.float64).max - val = val.astype("c16") - - # GH#32878 used to coerce val to inf+0.000000e+00j - ser[0] = val - assert ser[0] == val - expected = Series([val, 1, 2, 3, 4], dtype="c16") - tm.assert_series_equal(ser, expected) - - def test_setitem_int_as_positional_fallback_deprecation(): # GH#42215 deprecated falling back to positional on __setitem__ with an # int not contained in the index