diff options
author | David Freese <dfreese@stanford.edu> | 2015-06-18 11:53:11 -0700 |
---|---|---|
committer | David Freese <dfreese@stanford.edu> | 2016-01-12 14:38:02 -0800 |
commit | 6e699948c2b6098ec1a6e135241bc24e4df9a4d1 (patch) | |
tree | 551f4d6779ffc378d43c59c8dd63341a02ef7289 /numpy/lib | |
parent | 2df298d9ac469ec60a29373ea60cd17e0c4fd970 (diff) | |
download | numpy-6e699948c2b6098ec1a6e135241bc24e4df9a4d1.tar.gz |
BUG: Fix nanpercentile crash on all-nan slices
Fix bug where nanpercentile would crash with an all-nan slices when
given multiple percentiles. Also corrects behavior where array sizes
different from numpy.percentile would be returned with keepdims enabled.
Fix #5760
Diffstat (limited to 'numpy/lib')
-rw-r--r-- | numpy/lib/nanfunctions.py | 11 | ||||
-rw-r--r-- | numpy/lib/tests/test_nanfunctions.py | 26 |
2 files changed, 34 insertions, 3 deletions
diff --git a/numpy/lib/nanfunctions.py b/numpy/lib/nanfunctions.py index 1e3208ac8..6b28b4a35 100644 --- a/numpy/lib/nanfunctions.py +++ b/numpy/lib/nanfunctions.py @@ -975,7 +975,11 @@ def _nanpercentile(a, q, axis=None, out=None, overwrite_input=False, else: result = np.apply_along_axis(_nanpercentile1d, axis, a, q, overwrite_input, interpolation) - + # apply_along_axis fills in collapsed axis with results. + # Move that axis to the beginning to match percentile's + # convention. + if q.ndim != 0: + result = np.swapaxes(result, 0, axis) if out is not None: out[...] = result return result @@ -991,7 +995,10 @@ def _nanpercentile1d(arr1d, q, overwrite_input=False, interpolation='linear'): s = np.where(c)[0] if s.size == arr1d.size: warnings.warn("All-NaN slice encountered", RuntimeWarning) - return np.nan + if q.ndim == 0: + return np.nan + else: + return np.nan * np.ones((len(q),)) elif s.size == 0: return np.percentile(arr1d, q, overwrite_input=overwrite_input, interpolation=interpolation) diff --git a/numpy/lib/tests/test_nanfunctions.py b/numpy/lib/tests/test_nanfunctions.py index 7a7b37b98..51cdf2af2 100644 --- a/numpy/lib/tests/test_nanfunctions.py +++ b/numpy/lib/tests/test_nanfunctions.py @@ -654,7 +654,8 @@ class TestNanFunctions_Percentile(TestCase): tgt = [np.percentile(d, 28) for d in _rdat] res = np.nanpercentile(_ndat, 28, axis=1) assert_almost_equal(res, tgt) - tgt = [np.percentile(d, (28, 98)) for d in _rdat] + # Transpose the array to fit the output convention of numpy.percentile + tgt = np.transpose([np.percentile(d, (28, 98)) for d in _rdat]) res = np.nanpercentile(_ndat, (28, 98), axis=1) assert_almost_equal(res, tgt) @@ -702,6 +703,29 @@ class TestNanFunctions_Percentile(TestCase): assert_raises(IndexError, np.nanpercentile, d, q=5, axis=(0, 4)) assert_raises(ValueError, np.nanpercentile, d, q=5, axis=(1, 1)) + def test_multiple_percentiles(self): + perc = [50, 100] + mat = np.ones((4, 3)) + nan_mat = np.nan * mat + # For checking consistency in higher dimensional case + large_mat = np.ones((3, 4, 5)) + large_mat[:, 0:2:4, :] = 0 + large_mat[:, :, 3:] = 2*large_mat[:, :, 3:] + for axis in [None, 0, 1]: + for keepdim in [False, True]: + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter('always') + val = np.percentile(mat, perc, axis=axis, keepdims=keepdim) + nan_val = np.nanpercentile(nan_mat, perc, axis=axis, + keepdims=keepdim) + assert_equal(nan_val.shape, val.shape) + + val = np.percentile(large_mat, perc, axis=axis, + keepdims=keepdim) + nan_val = np.nanpercentile(large_mat, perc, axis=axis, + keepdims=keepdim) + assert_equal(nan_val, val) + if __name__ == "__main__": run_module_suite() |