diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index b6d5493aefaa9..d6269fabf0f00 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -296,7 +296,7 @@ Sparse ^^^^^^ - Bug in :meth:`DataFrame.sparse.to_coo` raising ``KeyError`` with columns that are a numeric :class:`Index` without a 0 (:issue:`18414`) -- +- Bug in :meth:`SparseArray.astype` with ``copy=False`` producing incorrect results when going from integer dtype to floating dtype (:issue:`34456`) - ExtensionArray diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 08e193acdf5ea..0915043f8fd46 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -1133,11 +1133,11 @@ def astype_nansafe( ) raise ValueError(msg) - if copy or is_object_dtype(arr) or is_object_dtype(dtype): + if copy or is_object_dtype(arr.dtype) or is_object_dtype(dtype): # Explicit copy, or required since NumPy can't view from / to object. return arr.astype(dtype, copy=True) - return arr.view(dtype) + return arr.astype(dtype, copy=copy) def soft_convert_objects( diff --git a/pandas/tests/arrays/sparse/test_array.py b/pandas/tests/arrays/sparse/test_array.py index 46edde62b510e..7f1b0f49ebd1e 100644 --- a/pandas/tests/arrays/sparse/test_array.py +++ b/pandas/tests/arrays/sparse/test_array.py @@ -563,6 +563,14 @@ def test_astype_nan_raises(self): with pytest.raises(ValueError, match="Cannot convert non-finite"): arr.astype(int) + def test_astype_copy_false(self): + # GH#34456 bug caused by using .view instead of .astype in astype_nansafe + arr = SparseArray([1, 2, 3]) + + result = arr.astype(float, copy=False) + expected = SparseArray([1.0, 2.0, 3.0], fill_value=0.0) + tm.assert_sp_array_equal(result, expected) + def test_set_fill_value(self): arr = SparseArray([1.0, np.nan, 2.0], fill_value=np.nan) arr.fill_value = 2 diff --git a/pandas/tests/dtypes/test_common.py b/pandas/tests/dtypes/test_common.py index 54bac7deded6c..8df61394e8e7e 100644 --- a/pandas/tests/dtypes/test_common.py +++ b/pandas/tests/dtypes/test_common.py @@ -724,6 +724,17 @@ def test_astype_nansafe(val, typ): astype_nansafe(arr, dtype=typ) +def test_astype_nansafe_copy_false(any_int_dtype): + # GH#34457 use astype, not view + arr = np.array([1, 2, 3], dtype=any_int_dtype) + + dtype = np.dtype("float64") + result = astype_nansafe(arr, dtype, copy=False) + + expected = np.array([1.0, 2.0, 3.0], dtype=dtype) + tm.assert_numpy_array_equal(result, expected) + + @pytest.mark.parametrize("from_type", [np.datetime64, np.timedelta64]) @pytest.mark.parametrize( "to_type",