diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index b458b0f998255..e6bc422b52e89 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -769,6 +769,7 @@ Sparse - Bug in :class:`SparseFrame` constructor where passing ``None`` as the data would cause ``default_fill_value`` to be ignored (:issue:`16807`) - Bug in :class:`SparseDataFrame` when adding a column in which the length of values does not match length of index, ``AssertionError`` is raised instead of raising ``ValueError`` (:issue:`25484`) - Introduce a better error message in :meth:`Series.sparse.from_coo` so it returns a ``TypeError`` for inputs that are not coo matrices (:issue:`26554`) +- Bug in :func:`numpy.modf` on a :class:`SparseArray`. Now a tuple of :class:`SparseArray` is returned. Other ^^^^^ diff --git a/pandas/core/arrays/sparse.py b/pandas/core/arrays/sparse.py index 5e636b5105e56..3dda6868a80da 100644 --- a/pandas/core/arrays/sparse.py +++ b/pandas/core/arrays/sparse.py @@ -1697,6 +1697,17 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): # No alignment necessary. sp_values = getattr(ufunc, method)(self.sp_values, **kwargs) fill_value = getattr(ufunc, method)(self.fill_value, **kwargs) + + if isinstance(sp_values, tuple): + # multiple outputs. e.g. modf + arrays = tuple( + self._simple_new(sp_value, + self.sp_index, + SparseDtype(sp_value.dtype, fv)) + for sp_value, fv in zip(sp_values, fill_value) + ) + return arrays + return self._simple_new(sp_values, self.sp_index, SparseDtype(sp_values.dtype, fill_value)) diff --git a/pandas/tests/arrays/sparse/test_array.py b/pandas/tests/arrays/sparse/test_array.py index c0a1b32079044..231b5a92dbb3a 100644 --- a/pandas/tests/arrays/sparse/test_array.py +++ b/pandas/tests/arrays/sparse/test_array.py @@ -1071,6 +1071,16 @@ def test_ufunc_args(self): result = SparseArray([2, 0, 1, -1], fill_value=1) tm.assert_sp_array_equal(np.add(sparse, 1), result) + @pytest.mark.parametrize('fill_value', [0.0, np.nan]) + def test_modf(self, fill_value): + # https://github.com/pandas-dev/pandas/issues/26946 + sparse = pd.SparseArray([fill_value] * 10 + [1.1, 2.2], + fill_value=fill_value) + r1, r2 = np.modf(sparse) + e1, e2 = np.modf(np.asarray(sparse)) + tm.assert_sp_array_equal(r1, pd.SparseArray(e1, fill_value=fill_value)) + tm.assert_sp_array_equal(r2, pd.SparseArray(e2, fill_value=fill_value)) + def test_nbytes_integer(self): arr = SparseArray([1, 0, 0, 0, 2], kind='integer') result = arr.nbytes