diff options
author | Marten van Kerkwijk <mhvk@astro.utoronto.ca> | 2018-03-27 15:40:46 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-27 15:40:46 -0400 |
commit | bea761424753c0612a65a6a91d44f9a81bdc4c12 (patch) | |
tree | 56213b3278642768df325127c27caf561d1cdf40 | |
parent | a2d19a8ca931fc183ad8cfb4f18bd826134e9773 (diff) | |
parent | 093c308fcc4249d8a0f1336827d8eb9ad1e7d274 (diff) | |
download | python-numpy-upstream-git.tar.gz python-numpy-upstream-git.tar.bz2 python-numpy-upstream-git.zip |
Merge pull request #10619 from eric-wieser/fix-notmasked_contiguousv1.15.0upstream-git
BUG: np.ma.flatnotmasked_contiguous behaves differently on mask=nomask and mask=zeros
-rw-r--r-- | doc/release/1.15.0-notes.rst | 9 | ||||
-rw-r--r-- | numpy/ma/extras.py | 50 | ||||
-rw-r--r-- | numpy/ma/tests/test_extras.py | 42 |
3 files changed, 73 insertions, 28 deletions
diff --git a/doc/release/1.15.0-notes.rst b/doc/release/1.15.0-notes.rst index fadce7684..6e4ef7eed 100644 --- a/doc/release/1.15.0-notes.rst +++ b/doc/release/1.15.0-notes.rst @@ -46,6 +46,15 @@ Future Changes Compatibility notes =================== +``np.ma.notmasked_contiguous`` and ``np.ma.flatnotmasked_contiguous`` always return lists +----------------------------------------------------------------------------------------- +This was always the documented behavior, but in reality the result used to be +any of slice, None, or list. + +All downstream users seem to use detect the `None` result from +``flatnotmasked_contiguous`` and replace it with ``[]``. +These callers will continue to work as before. + C API changes ============= diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index e247fe170..8272dced9 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -1620,7 +1620,10 @@ def flatnotmasked_contiguous(a): Returns ------- slice_list : list - A sorted sequence of slices (start index, end index). + A sorted sequence of `slice` objects (start index, end index). + + ..versionchanged:: 1.15.0 + Now returns an empty list instead of None for a fully masked array See Also -------- @@ -1635,7 +1638,7 @@ def flatnotmasked_contiguous(a): -------- >>> a = np.ma.arange(10) >>> np.ma.flatnotmasked_contiguous(a) - slice(0, 10, None) + [slice(0, 10, None)] >>> mask = (a < 3) | (a > 8) | (a == 5) >>> a[mask] = np.ma.masked @@ -1645,13 +1648,13 @@ def flatnotmasked_contiguous(a): >>> np.ma.flatnotmasked_contiguous(a) [slice(3, 5, None), slice(6, 9, None)] >>> a[:] = np.ma.masked - >>> print(np.ma.flatnotmasked_edges(a)) - None + >>> np.ma.flatnotmasked_contiguous(a) + [] """ m = getmask(a) if m is nomask: - return slice(0, a.size, None) + return [slice(0, a.size)] i = 0 result = [] for (k, g) in itertools.groupby(m.ravel()): @@ -1659,7 +1662,7 @@ def flatnotmasked_contiguous(a): if not k: result.append(slice(i, i + n)) i += n - return result or None + return result def notmasked_contiguous(a, axis=None): """ @@ -1671,7 +1674,8 @@ def notmasked_contiguous(a, axis=None): The input array. axis : int, optional Axis along which to perform the operation. - If None (default), applies to a flattened version of the array. + If None (default), applies to a flattened version of the array, and this + is the same as `flatnotmasked_contiguous`. Returns ------- @@ -1679,6 +1683,8 @@ def notmasked_contiguous(a, axis=None): A list of slices (start and end indexes) of unmasked indexes in the array. + If the input is 2d and axis is specified, the result is a list of lists. + See Also -------- flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges, @@ -1690,17 +1696,35 @@ def notmasked_contiguous(a, axis=None): Examples -------- - >>> a = np.arange(9).reshape((3, 3)) + >>> a = np.arange(12).reshape((3, 4)) >>> mask = np.zeros_like(a) - >>> mask[1:, 1:] = 1 - + >>> mask[1:, :-1] = 1; mask[0, 1] = 1; mask[-1, 0] = 0 >>> ma = np.ma.array(a, mask=mask) + >>> ma + masked_array( + data=[[0, --, 2, 3], + [--, --, --, 7], + [8, --, --, 11]], + mask=[[False, True, False, False], + [ True, True, True, False], + [False, True, True, False]], + fill_value=999999) >>> np.array(ma[~ma.mask]) - array([0, 1, 2, 3, 6]) + array([ 0, 2, 3, 7, 8, 11]) >>> np.ma.notmasked_contiguous(ma) - [slice(0, 4, None), slice(6, 7, None)] + [slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)] + + >>> np.ma.notmasked_contiguous(ma, axis=0) + [[slice(0, 1, None), slice(2, 3, None)], # column broken into two segments + [], # fully masked column + [slice(0, 1, None)], + [slice(0, 3, None)]] + >>> np.ma.notmasked_contiguous(ma, axis=1) + [[slice(0, 1, None), slice(2, 4, None)], # row broken into two segments + [slice(3, 4, None)], + [slice(0, 1, None), slice(3, 4, None)]] """ a = asarray(a) nd = a.ndim @@ -1717,7 +1741,7 @@ def notmasked_contiguous(a, axis=None): # for i in range(a.shape[other]): idx[other] = i - result.append(flatnotmasked_contiguous(a[tuple(idx)]) or None) + result.append(flatnotmasked_contiguous(a[tuple(idx)])) return result diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py index d1c1aa63e..95319eb65 100644 --- a/numpy/ma/tests/test_extras.py +++ b/numpy/ma/tests/test_extras.py @@ -128,7 +128,10 @@ class TestGeneric(object): a = arange(10) # No mask test = flatnotmasked_contiguous(a) - assert_equal(test, slice(0, a.size)) + assert_equal(test, [slice(0, a.size)]) + # mask of all false + a.mask = np.zeros(10, dtype=bool) + assert_equal(test, [slice(0, a.size)]) # Some mask a[(a < 3) | (a > 8) | (a == 5)] = masked test = flatnotmasked_contiguous(a) @@ -136,7 +139,7 @@ class TestGeneric(object): # a[:] = masked test = flatnotmasked_contiguous(a) - assert_equal(test, None) + assert_equal(test, []) class TestAverage(object): @@ -368,23 +371,32 @@ class TestNotMasked(object): a = masked_array(np.arange(24).reshape(3, 8), mask=[[0, 0, 0, 0, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], - [0, 0, 0, 0, 0, 0, 1, 0], ]) + [0, 0, 0, 0, 0, 0, 1, 0]]) tmp = notmasked_contiguous(a, None) - assert_equal(tmp[-1], slice(23, 24, None)) - assert_equal(tmp[-2], slice(16, 22, None)) - assert_equal(tmp[-3], slice(0, 4, None)) - # + assert_equal(tmp, [ + slice(0, 4, None), + slice(16, 22, None), + slice(23, 24, None) + ]) + tmp = notmasked_contiguous(a, 0) - assert_(len(tmp[-1]) == 1) - assert_(tmp[-2] is None) - assert_equal(tmp[-3], tmp[-1]) - assert_(len(tmp[0]) == 2) + assert_equal(tmp, [ + [slice(0, 1, None), slice(2, 3, None)], + [slice(0, 1, None), slice(2, 3, None)], + [slice(0, 1, None), slice(2, 3, None)], + [slice(0, 1, None), slice(2, 3, None)], + [slice(2, 3, None)], + [slice(2, 3, None)], + [], + [slice(2, 3, None)] + ]) # tmp = notmasked_contiguous(a, 1) - assert_equal(tmp[0][-1], slice(0, 4, None)) - assert_(tmp[1] is None) - assert_equal(tmp[2][-1], slice(7, 8, None)) - assert_equal(tmp[2][-2], slice(0, 6, None)) + assert_equal(tmp, [ + [slice(0, 4, None)], + [], + [slice(0, 6, None), slice(7, 8, None)] + ]) class TestCompressFunctions(object): |