From 54d5bb8a0df0f42b1fcadf8a20b90caa6c762a2c Mon Sep 17 00:00:00 2001 From: Nishanth Pradeep Date: Sun, 20 May 2018 13:10:15 -0500 Subject: [PATCH 1/4] BUG: Fix inconsistency between the shape properties of SparseSeries and SparseArray (#21126) --- pandas/core/sparse/array.py | 8 +++++++- pandas/tests/sparse/test_array.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pandas/core/sparse/array.py b/pandas/core/sparse/array.py index 5532d7522cd2d..dbbace56f6bab 100644 --- a/pandas/core/sparse/array.py +++ b/pandas/core/sparse/array.py @@ -290,7 +290,9 @@ def __reduce__(self): """Necessary for making this object picklable""" object_state = list(np.ndarray.__reduce__(self)) subclass_state = self.fill_value, self.sp_index - object_state[2] = (object_state[2], subclass_state) + object_state[2] = list(object_state[2]) + object_state[2][1] = super(SparseArray, self).shape + object_state[2] = (tuple(object_state[2]), subclass_state) return tuple(object_state) def __setstate__(self, state): @@ -339,6 +341,10 @@ def values(self): output.put(int_index.indices, self) return output + @property + def shape(self): + return (len(self),) + @property def sp_values(self): # caching not an option, leaks memory diff --git a/pandas/tests/sparse/test_array.py b/pandas/tests/sparse/test_array.py index 6c0c83cf65ff7..ea4255b945612 100644 --- a/pandas/tests/sparse/test_array.py +++ b/pandas/tests/sparse/test_array.py @@ -454,6 +454,16 @@ def test_values_asarray(self): assert_almost_equal(self.arr.to_dense(), self.arr_data) assert_almost_equal(self.arr.sp_values, np.asarray(self.arr)) + def test_shape(self): + out = SparseArray([0, 0, 0, 0, 0]) + assert out.shape == (5,) + + out = SparseArray([]) + assert out.shape == (0,) + + out = SparseArray([0]) + assert out.shape == (1,) + def test_to_dense(self): vals = np.array([1, np.nan, np.nan, 3, np.nan]) res = SparseArray(vals).to_dense() From 0538861892a780bec59f2873edf31bc0b88ebb87 Mon Sep 17 00:00:00 2001 From: Nishanth Pradeep Date: Sat, 26 May 2018 18:26:46 -0500 Subject: [PATCH 2/4] Added issue number to test_shape --- pandas/tests/sparse/test_array.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/tests/sparse/test_array.py b/pandas/tests/sparse/test_array.py index ea4255b945612..9ba1e77f3522a 100644 --- a/pandas/tests/sparse/test_array.py +++ b/pandas/tests/sparse/test_array.py @@ -455,6 +455,7 @@ def test_values_asarray(self): assert_almost_equal(self.arr.sp_values, np.asarray(self.arr)) def test_shape(self): + # GH 21126 out = SparseArray([0, 0, 0, 0, 0]) assert out.shape == (5,) From c4bbef45a4bd388e279a0387200b26aadb779ed2 Mon Sep 17 00:00:00 2001 From: Nishanth Pradeep Date: Sun, 27 May 2018 14:50:19 -0500 Subject: [PATCH 3/4] Added what's new entry --- doc/source/whatsnew/v0.23.1.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/source/whatsnew/v0.23.1.txt b/doc/source/whatsnew/v0.23.1.txt index 4876678baaa6e..6a6606c634e55 100644 --- a/doc/source/whatsnew/v0.23.1.txt +++ b/doc/source/whatsnew/v0.23.1.txt @@ -67,6 +67,11 @@ Categorical - Bug in :func:`pandas.util.testing.assert_index_equal` which raised ``AssertionError`` incorrectly, when comparing two :class:`CategoricalIndex` objects with param ``check_categorical=False`` (:issue:`19776`) +Sparse +^^^^^^ + +- Bug in :attr:`SparseArray.shape` ignores ``fill_values`` (:issue:`21126`) + Conversion ^^^^^^^^^^ From 7cc18c5b28d84158be632f194159ffa5958fd07c Mon Sep 17 00:00:00 2001 From: Nishanth Pradeep Date: Wed, 30 May 2018 20:39:20 -0500 Subject: [PATCH 4/4] Refactored __reduce__, parametrized tests, and reworded release doc --- doc/source/whatsnew/v0.23.1.txt | 2 +- pandas/core/sparse/array.py | 5 ++--- pandas/tests/sparse/test_array.py | 18 +++++++++--------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/doc/source/whatsnew/v0.23.1.txt b/doc/source/whatsnew/v0.23.1.txt index 6a6606c634e55..f5df37cd42e4f 100644 --- a/doc/source/whatsnew/v0.23.1.txt +++ b/doc/source/whatsnew/v0.23.1.txt @@ -70,7 +70,7 @@ Categorical Sparse ^^^^^^ -- Bug in :attr:`SparseArray.shape` ignores ``fill_values`` (:issue:`21126`) +- Bug in :attr:`SparseArray.shape` which previously only returned the shape :attr:`SparseArray.sp_values` (:issue:`21126`) Conversion ^^^^^^^^^^ diff --git a/pandas/core/sparse/array.py b/pandas/core/sparse/array.py index dbbace56f6bab..ff58f7d104ff9 100644 --- a/pandas/core/sparse/array.py +++ b/pandas/core/sparse/array.py @@ -290,9 +290,8 @@ def __reduce__(self): """Necessary for making this object picklable""" object_state = list(np.ndarray.__reduce__(self)) subclass_state = self.fill_value, self.sp_index - object_state[2] = list(object_state[2]) - object_state[2][1] = super(SparseArray, self).shape - object_state[2] = (tuple(object_state[2]), subclass_state) + object_state[2] = self.sp_values.__reduce__()[2] + object_state[2] = (object_state[2], subclass_state) return tuple(object_state) def __setstate__(self, state): diff --git a/pandas/tests/sparse/test_array.py b/pandas/tests/sparse/test_array.py index 9ba1e77f3522a..b3330f866ba1f 100644 --- a/pandas/tests/sparse/test_array.py +++ b/pandas/tests/sparse/test_array.py @@ -454,16 +454,16 @@ def test_values_asarray(self): assert_almost_equal(self.arr.to_dense(), self.arr_data) assert_almost_equal(self.arr.sp_values, np.asarray(self.arr)) - def test_shape(self): + @pytest.mark.parametrize('data,shape,dtype', [ + ([0, 0, 0, 0, 0], (5,), None), + ([], (0,), None), + ([0], (1,), None), + (['A', 'A', np.nan, 'B'], (4,), np.object) + ]) + def test_shape(self, data, shape, dtype): # GH 21126 - out = SparseArray([0, 0, 0, 0, 0]) - assert out.shape == (5,) - - out = SparseArray([]) - assert out.shape == (0,) - - out = SparseArray([0]) - assert out.shape == (1,) + out = SparseArray(data, dtype=dtype) + assert out.shape == shape def test_to_dense(self): vals = np.array([1, np.nan, np.nan, 3, np.nan])