diff --git a/pandas/core/construction.py b/pandas/core/construction.py index f01d8822241c9..121f98b8368ca 100644 --- a/pandas/core/construction.py +++ b/pandas/core/construction.py @@ -36,6 +36,8 @@ ) from pandas.core.dtypes.common import ( ensure_object, + is_float_dtype, + is_integer_dtype, is_list_like, is_object_dtype, pandas_dtype, @@ -510,11 +512,18 @@ def sanitize_masked_array(data: ma.MaskedArray) -> np.ndarray: Convert numpy MaskedArray to ensure mask is softened. """ mask = ma.getmaskarray(data) + original = data + original_dtype = data.dtype if mask.any(): dtype, fill_value = maybe_promote(data.dtype, np.nan) dtype = cast(np.dtype, dtype) data = ma.asarray(data.astype(dtype, copy=True)) data.soften_mask() # set hardmask False if it was True + if not mask.all(): + idx = np.unravel_index(np.nanargmax(data, axis=None), data.shape) + if not mask[idx] and int(data[idx]) != original[idx]: + if is_integer_dtype(original_dtype) and is_float_dtype(data.dtype): + data = ma.asarray(original, "object") data[mask] = fill_value else: data = data.copy() diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index 00c614cf72c20..0197dc448920f 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -2151,6 +2151,31 @@ def test_inference_on_pandas_objects(self): result = Series(idx) assert result.dtype != np.object_ + def test_series_constructor_maskedarray_int_overflow(self): + # GH#56566 + mx = ma.masked_array( + [ + 4873214862074861312, + 4875446630161458944, + 4824652147895424384, + 0, + 3526420114272476800, + ], + mask=[0, 0, 0, 1, 0], + ) + result = Series(mx, dtype="Int64") + expected = np.array( + [ + 4873214862074861312, + 4875446630161458944, + 4824652147895424384, + 3526420114272476800, + ], + dtype="int64", + ) + result = np.array(result.dropna(ignore_index=True).values) + assert np.all(expected == result) + class TestSeriesConstructorIndexCoercion: def test_series_constructor_datetimelike_index_coercion(self):