diff options
-rw-r--r-- | numpy/ma/core.py | 5 | ||||
-rw-r--r-- | numpy/ma/extras.py | 76 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 8 | ||||
-rw-r--r-- | numpy/ma/tests/test_extras.py | 31 |
4 files changed, 110 insertions, 10 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py index 105dd30ec..4b4fdc2b9 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -2513,7 +2513,10 @@ class MaskedArray(ndarray): self._mask = _mask # Finalize the mask ........... if self._mask is not nomask: - self._mask.shape = self.shape + try: + self._mask.shape = self.shape + except ValueError: + self._mask = nomask return #.................................. def __array_wrap__(self, obj, context=None): diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index 6041b7e2c..85cc834c1 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -13,8 +13,9 @@ __date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' __all__ = ['apply_along_axis', 'atleast_1d', 'atleast_2d', 'atleast_3d', 'average', - 'column_stack','compress_cols','compress_rowcols', 'compress_rows', - 'count_masked', 'corrcoef', 'cov', + 'clump_masked', 'clump_unmasked', 'column_stack', 'compress_cols', + 'compress_rowcols', 'compress_rows', 'count_masked', 'corrcoef', + 'cov', 'diagflat', 'dot','dstack', 'ediff1d', 'flatnotmasked_contiguous', 'flatnotmasked_edges', @@ -30,7 +31,7 @@ __all__ = ['apply_along_axis', 'atleast_1d', 'atleast_2d', 'atleast_3d', 'vander', 'vstack', ] -from itertools import groupby +import itertools import warnings import core as ma @@ -1366,7 +1367,7 @@ def flatnotmasked_contiguous(a): if len(unmasked) == 0: return None result = [] - for k, group in groupby(enumerate(unmasked), lambda (i,x):i-x): + for (k, group) in itertools.groupby(enumerate(unmasked), lambda (i,x):i-x): tmp = np.array([g[1] for g in group], int) # result.append((tmp.size, tuple(tmp[[0,-1]]))) result.append( slice(tmp[0], tmp[-1]) ) @@ -1411,6 +1412,73 @@ def notmasked_contiguous(a, axis=None): return result +def _ezclump(mask): + """ + Finds the clumps (groups of data with the same values) for a 1D bool array. + + Returns a series of slices. + """ + #def clump_masked(a): + if mask.ndim > 1: + mask = mask.ravel() + idx = (mask[1:] - mask[:-1]).nonzero() + idx = idx[0] + 1 + slices = [slice(left, right) + for (left, right) in zip(itertools.chain([0], idx), + itertools.chain(idx, [len(mask)]),)] + return slices + + +def clump_unmasked(a): + """ + Returns a list of slices corresponding to the unmasked clumps of a 1D array. + + Examples + -------- + >>> a = ma.masked_array(np.arange(10)) + >>> a[[0, 1, 2, 6, 8, 9]] = ma.masked + >>> clump_unmasked(a) + [slice(3, 6, None), slice(7, 8, None)] + + .. versionadded:: 1.4.0 + """ + mask = getattr(a, '_mask', nomask) + if mask is nomask: + return [slice(0, a.size)] + slices = _ezclump(mask) + if a[0] is masked: + result = slices[1::2] + else: + result = slices[::2] + return result + + +def clump_masked(a): + """ + Returns a list of slices corresponding to the masked clumps of a 1D array. + + Examples + -------- + >>> a = ma.masked_array(np.arange(10)) + >>> a[[0, 1, 2, 6, 8, 9]] = ma.masked + >>> clump_masked(a) + [slice(0, 3, None), slice(6, 7, None), slice(8, None, None)] + + .. versionadded:: 1.4.0 + """ + mask = ma.getmask(a) + if mask is nomask: + return [] + slices = _ezclump(mask) + if len(slices): + if a[0] is masked: + slices = slices[::2] + else: + slices = slices[1::2] + return slices + + + #####-------------------------------------------------------------------------- #---- Polynomial fit --- #####-------------------------------------------------------------------------- diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index 549f864b7..b6222a8cb 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -783,6 +783,12 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal(amaximum, np.maximum.outer(a,a)) + def test_minmax_reduce(self): + "Test np.min/maximum.reduce on array w/ full False mask" + a = array([1, 2, 3], mask=[False, False, False]) + b = np.maximum.reduce(a) + assert_equal(b, 3) + def test_minmax_funcs_with_output(self): "Tests the min/max functions with explicit outputs" mask = np.random.rand(12).round() @@ -1359,7 +1365,7 @@ class TestFillingValues(TestCase): assert_equal(test[1][0], maximum_fill_value(a['B']['BA'])) assert_equal(test[1][1], maximum_fill_value(a['B']['BB'])) assert_equal(test[1], maximum_fill_value(a['B'])) - + #------------------------------------------------------------------------------ diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py index 089a4e58a..687fc9b81 100644 --- a/numpy/ma/tests/test_extras.py +++ b/numpy/ma/tests/test_extras.py @@ -70,7 +70,24 @@ class TestGeneric(TestCase): mask=[(1, (1, 1)), (1, (1, 1))], dtype=dt) test = masked_all_like(control) assert_equal(test, control) + + def test_clump_masked(self): + "Test clump_masked" + a = masked_array(np.arange(10)) + a[[0, 1, 2, 6, 8, 9]] = masked # + test = clump_masked(a) + control = [slice(0, 3), slice(6, 7), slice(8, 10)] + assert_equal(test, control) + + def test_clump_unmasked(self): + "Test clump_unmasked" + a = masked_array(np.arange(10)) + a[[0, 1, 2, 6, 8, 9]] = masked + test = clump_unmasked(a) + control = [slice(3, 6), slice(7, 8),] + assert_equal(test, control) + class TestAverage(TestCase): @@ -151,8 +168,13 @@ class TestAverage(TestCase): a2dma = average(a2dm, axis=1) assert_equal(a2dma, [1.5, 4.0]) + + class TestConcatenator(TestCase): - "Tests for mr_, the equivalent of r_ for masked arrays." + """ + Tests for mr_, the equivalent of r_ for masked arrays. + """ + def test_1d(self): "Tests mr_ on 1D arrays." assert_array_equal(mr_[1,2,3,4,5,6],array([1,2,3,4,5,6])) @@ -186,7 +208,10 @@ class TestConcatenator(TestCase): class TestNotMasked(TestCase): - "Tests notmasked_edges and notmasked_contiguous." + """ + Tests notmasked_edges and notmasked_contiguous. + """ + def test_edges(self): "Tests unmasked_edges" data = masked_array(np.arange(25).reshape(5, 5), @@ -222,7 +247,6 @@ class TestNotMasked(TestCase): assert_equal(test[1], [(0, 1, 2, 4), (4, 2, 4, 4)]) - def test_contiguous(self): "Tests notmasked_contiguous" a = masked_array(np.arange(24).reshape(3,8), @@ -248,7 +272,6 @@ class TestNotMasked(TestCase): - class Test2DFunctions(TestCase): "Tests 2D functions" def test_compress2d(self): |