[Python-modules-commits] [python-numpy] 01/04: BUG: fix wrong masked median for some special cases

Sandro Tosi morph at moszumanska.debian.org
Fri Jan 20 01:16:32 UTC 2017


This is an automated email from the git hooks/post-receive script.

morph pushed a commit to branch master
in repository python-numpy.

commit 083f1eedacba2e880991eccee3631f8f7b0deaa9
Author: Julian Taylor <jtaylor.debian at googlemail.com>
Date:   Tue Jan 17 13:04:44 2017 +0100

    BUG: fix wrong masked median for some special cases
    
    the masked nans which are equivalent to valid infs must be replaced
    with infs earlier otherwise the inf is lost in the masked sum of the low
    and high part.
    Closes gh-8487
---
 numpy/lib/tests/test_nanfunctions.py | 12 ++++++++++++
 numpy/ma/extras.py                   | 19 +++++++++++++------
 numpy/ma/tests/test_extras.py        | 22 ++++++++++++++++++++++
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/numpy/lib/tests/test_nanfunctions.py b/numpy/lib/tests/test_nanfunctions.py
index e194233..2b31045 100644
--- a/numpy/lib/tests/test_nanfunctions.py
+++ b/numpy/lib/tests/test_nanfunctions.py
@@ -710,6 +710,18 @@ class TestNanFunctions_Median(TestCase):
                 a = np.array([[inf, inf], [inf, inf]])
                 assert_equal(np.nanmedian(a, axis=1), inf)
 
+                a = np.array([[inf, 7, -inf, -9],
+                              [-10, np.nan, np.nan, 5],
+                              [4, np.nan, np.nan, inf]],
+                              dtype=np.float32)
+                if inf > 0:
+                    assert_equal(np.nanmedian(a, axis=0), [4., 7., -inf, 5.])
+                    assert_equal(np.nanmedian(a), 4.5)
+                else:
+                    assert_equal(np.nanmedian(a, axis=0), [-10., 7., -inf, -9.])
+                    assert_equal(np.nanmedian(a), -2.5)
+                assert_equal(np.nanmedian(a, axis=-1), [-1., -2.5, inf])
+
                 for i in range(0, 10):
                     for j in range(1, 10):
                         a = np.array([([np.nan] * i) + ([inf] * j)] * 2)
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index 1774ece..0a60ea3 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -758,6 +758,19 @@ def _median(a, axis=None, out=None, overwrite_input=False):
     ind[axis] = np.minimum(h, asorted.shape[axis] - 1)
     high = asorted[tuple(ind)]
 
+    def replace_masked(s):
+        # Replace masked entries with minimum_full_value unless it all values
+        # are masked. This is required as the sort order of values equal or
+        # larger than the fill value is undefined and a valid value placed
+        # elsewhere, e.g. [4, --, inf].
+        if np.ma.is_masked(s):
+            rep = (~np.all(asorted.mask, axis=axis)) & s.mask
+            s.data[rep] = np.ma.minimum_fill_value(asorted)
+            s.mask[rep] = False
+
+    replace_masked(low)
+    replace_masked(high)
+
     # duplicate high if odd number of elements so mean does nothing
     odd = counts % 2 == 1
     np.copyto(low, high, where=odd)
@@ -776,12 +789,6 @@ def _median(a, axis=None, out=None, overwrite_input=False):
     else:
         s = np.ma.mean([low, high], axis=0, out=out)
 
-    # if result is masked either the input contained enough minimum_fill_value
-    # so that it would be the median or all values masked
-    if np.ma.is_masked(s):
-        rep = (~np.all(asorted.mask, axis=axis)) & s.mask
-        s.data[rep] = np.ma.minimum_fill_value(asorted)
-        s.mask[rep] = False
     return s
 
 
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index fb16d92..58ac46f 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -667,6 +667,15 @@ class TestMedian(TestCase):
         r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
                                              [np.inf, np.inf]]), axis=None)
         assert_equal(r, np.inf)
+        # all masked
+        r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
+                                             [np.inf, np.inf]], mask=True),
+                         axis=-1)
+        assert_equal(r.mask, True)
+        r = np.ma.median(np.ma.masked_array([[np.inf, np.inf],
+                                             [np.inf, np.inf]], mask=True),
+                         axis=None)
+        assert_equal(r.mask, True)
 
     def test_non_masked(self):
         x = np.arange(9)
@@ -992,6 +1001,19 @@ class TestMedian(TestCase):
             assert_equal(np.ma.median(a, axis=0), inf)
             assert_equal(np.ma.median(a, axis=1), inf)
 
+            a = np.array([[inf, 7, -inf, -9],
+                          [-10, np.nan, np.nan, 5],
+                          [4, np.nan, np.nan, inf]],
+                          dtype=np.float32)
+            a = np.ma.masked_array(a, mask=np.isnan(a))
+            if inf > 0:
+                assert_equal(np.ma.median(a, axis=0), [4., 7., -inf, 5.])
+                assert_equal(np.ma.median(a), 4.5)
+            else:
+                assert_equal(np.ma.median(a, axis=0), [-10., 7., -inf, -9.])
+                assert_equal(np.ma.median(a), -2.5)
+            assert_equal(np.ma.median(a, axis=1), [-1., -2.5, inf])
+
             for i in range(0, 10):
                 for j in range(1, 10):
                     a = np.array([([np.nan] * i) + ([inf] * j)] * 2)

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-numpy.git



More information about the Python-modules-commits mailing list