From cc4776b2f53b17e6cddbcc038921ee86da41e258 Mon Sep 17 00:00:00 2001 From: Licht-T Date: Fri, 29 Sep 2017 00:39:53 +0900 Subject: [PATCH 1/5] BUG: Add SparseArray.all --- pandas/compat/numpy/function.py | 6 ++++++ pandas/core/sparse/array.py | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/pandas/compat/numpy/function.py b/pandas/compat/numpy/function.py index ccbd3d9704e0c..44ae6b455840b 100644 --- a/pandas/compat/numpy/function.py +++ b/pandas/compat/numpy/function.py @@ -184,6 +184,12 @@ def validate_cum_func_with_skipna(skipna, args, kwargs, name): return skipna +ALLANY_DEFAULTS = OrderedDict() +ALLANY_DEFAULTS['dtype'] = None +ALLANY_DEFAULTS['out'] = None +validate_all = CompatValidator(ALLANY_DEFAULTS, fname='all', + method='both', max_fname_arg_count=1) + LOGICAL_FUNC_DEFAULTS = dict(out=None) validate_logical_func = CompatValidator(LOGICAL_FUNC_DEFAULTS, method='kwargs') diff --git a/pandas/core/sparse/array.py b/pandas/core/sparse/array.py index f965c91999a03..bf986c5524e02 100644 --- a/pandas/core/sparse/array.py +++ b/pandas/core/sparse/array.py @@ -614,6 +614,27 @@ def fillna(self, value, downcast=None): return self._simple_new(new_values, self.sp_index, fill_value=fill_value) + def all(self, axis=0, *args, **kwargs): + """ + Tests whether all elements evaluate True + + Returns + ------- + all : bool + + See Also + -------- + numpy.all + """ + nv.validate_all(args, kwargs) + + values = self.sp_values + + if len(values) != len(self) and not np.all(self.fill_value): + return False + + return values.all() + def sum(self, axis=0, *args, **kwargs): """ Sum of non-NA/null values From 6e1c91531ef843bc1dca304ee986fcb4815673f7 Mon Sep 17 00:00:00 2001 From: Licht-T Date: Mon, 18 Sep 2017 20:34:38 +0900 Subject: [PATCH 2/5] TST: Add tests of SparseArray.all --- pandas/tests/sparse/test_array.py | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/pandas/tests/sparse/test_array.py b/pandas/tests/sparse/test_array.py index b0a9182a265fe..e1aff8d598921 100644 --- a/pandas/tests/sparse/test_array.py +++ b/pandas/tests/sparse/test_array.py @@ -655,6 +655,50 @@ def test_fillna_overlap(self): class TestSparseArrayAnalytics(object): + @pytest.mark.parametrize('data,pos,neg', [ + ([True, True, True], True, False), + ([1, 2, 1], 1, 0), + ([1.0, 2.0, 1.0], 1.0, 0.0) + ]) + def test_all(self, data, pos, neg): + # GH 17570 + out = SparseArray(data).all() + assert out + + out = SparseArray(data, fill_value=pos).all() + assert out + + data[1] = neg + out = SparseArray(data).all() + assert not out + + out = SparseArray(data, fill_value=pos).all() + assert not out + + @pytest.mark.parametrize('data,pos,neg', [ + ([True, True, True], True, False), + ([1, 2, 1], 1, 0), + ([1.0, 2.0, 1.0], 1.0, 0.0) + ]) + def test_numpy_all(self, data, pos, neg): + # GH 17570 + out = np.all(SparseArray(data)) + assert out + + out = np.all(SparseArray(data, fill_value=pos)) + assert out + + data[1] = neg + out = np.all(SparseArray(data)) + assert not out + + out = np.all(SparseArray(data, fill_value=pos)) + assert not out + + msg = "the 'out' parameter is not supported" + tm.assert_raises_regex(ValueError, msg, np.all, + SparseArray(data), out=out) + def test_sum(self): data = np.arange(10).astype(float) out = SparseArray(data).sum() From 9e506a4c272d6f37ccb81270419499d88c324752 Mon Sep 17 00:00:00 2001 From: Licht-T Date: Fri, 29 Sep 2017 00:32:20 +0900 Subject: [PATCH 3/5] BUG: Add SparseArray.any --- pandas/compat/numpy/function.py | 2 ++ pandas/core/sparse/array.py | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/pandas/compat/numpy/function.py b/pandas/compat/numpy/function.py index 44ae6b455840b..d42be56963569 100644 --- a/pandas/compat/numpy/function.py +++ b/pandas/compat/numpy/function.py @@ -189,6 +189,8 @@ def validate_cum_func_with_skipna(skipna, args, kwargs, name): ALLANY_DEFAULTS['out'] = None validate_all = CompatValidator(ALLANY_DEFAULTS, fname='all', method='both', max_fname_arg_count=1) +validate_any = CompatValidator(ALLANY_DEFAULTS, fname='any', + method='both', max_fname_arg_count=1) LOGICAL_FUNC_DEFAULTS = dict(out=None) validate_logical_func = CompatValidator(LOGICAL_FUNC_DEFAULTS, method='kwargs') diff --git a/pandas/core/sparse/array.py b/pandas/core/sparse/array.py index bf986c5524e02..701577b6d14b0 100644 --- a/pandas/core/sparse/array.py +++ b/pandas/core/sparse/array.py @@ -635,6 +635,27 @@ def all(self, axis=0, *args, **kwargs): return values.all() + def any(self, axis=0, *args, **kwargs): + """ + Tests whether at least one of elements evaluate True + + Returns + ------- + any : bool + + See Also + -------- + numpy.any + """ + nv.validate_any(args, kwargs) + + values = self.sp_values + + if len(values) != len(self) and np.any(self.fill_value): + return True + + return values.any() + def sum(self, axis=0, *args, **kwargs): """ Sum of non-NA/null values From f5b4f6bfc416ea4101a4f2621064e7b3f924f118 Mon Sep 17 00:00:00 2001 From: Licht-T Date: Mon, 18 Sep 2017 22:13:06 +0900 Subject: [PATCH 4/5] TST: Add tests of SparseArray.any --- pandas/tests/sparse/test_array.py | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/pandas/tests/sparse/test_array.py b/pandas/tests/sparse/test_array.py index e1aff8d598921..cac8aaf270ec8 100644 --- a/pandas/tests/sparse/test_array.py +++ b/pandas/tests/sparse/test_array.py @@ -699,6 +699,50 @@ def test_numpy_all(self, data, pos, neg): tm.assert_raises_regex(ValueError, msg, np.all, SparseArray(data), out=out) + @pytest.mark.parametrize('data,pos,neg', [ + ([False, True, False], True, False), + ([0, 2, 0], 2, 0), + ([0.0, 2.0, 0.0], 2.0, 0.0) + ]) + def test_any(self, data, pos, neg): + # GH 17570 + out = SparseArray(data).any() + assert out + + out = SparseArray(data, fill_value=pos).any() + assert out + + data[1] = neg + out = SparseArray(data).any() + assert not out + + out = SparseArray(data, fill_value=pos).any() + assert not out + + @pytest.mark.parametrize('data,pos,neg', [ + ([False, True, False], True, False), + ([0, 2, 0], 2, 0), + ([0.0, 2.0, 0.0], 2.0, 0.0) + ]) + def test_numpy_any(self, data, pos, neg): + # GH 17570 + out = np.any(SparseArray(data)) + assert out + + out = np.any(SparseArray(data, fill_value=pos)) + assert out + + data[1] = neg + out = np.any(SparseArray(data)) + assert not out + + out = np.any(SparseArray(data, fill_value=pos)) + assert not out + + msg = "the 'out' parameter is not supported" + tm.assert_raises_regex(ValueError, msg, np.any, + SparseArray(data), out=out) + def test_sum(self): data = np.arange(10).astype(float) out = SparseArray(data).sum() From 94973e896ea766c101aab72b50969f2f3dd3c32e Mon Sep 17 00:00:00 2001 From: Licht-T Date: Mon, 18 Sep 2017 22:31:30 +0900 Subject: [PATCH 5/5] DOC: Add SparseArray.all and SparseArray.any to whatsnew note --- doc/source/whatsnew/v0.21.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 23a98d59554e9..84424413d65b5 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -544,6 +544,7 @@ Sparse - Bug in ``SparseSeries`` raises ``AttributeError`` when a dictionary is passed in as data (:issue:`16905`) - Bug in :func:`SparseDataFrame.fillna` not filling all NaNs when frame was instantiated from SciPy sparse matrix (:issue:`16112`) +- :func:`SparseArray.all` and :func:`SparseArray.any` are now implemented to handle ``SparseArray``, these were used but not implemented (:issue:`17570`) Reshaping