summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
authorDavid Freese <dfreese@stanford.edu>2015-06-18 11:53:11 -0700
committerDavid Freese <dfreese@stanford.edu>2016-01-12 14:38:02 -0800
commit6e699948c2b6098ec1a6e135241bc24e4df9a4d1 (patch)
tree551f4d6779ffc378d43c59c8dd63341a02ef7289 /numpy/lib
parent2df298d9ac469ec60a29373ea60cd17e0c4fd970 (diff)
downloadnumpy-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.py11
-rw-r--r--numpy/lib/tests/test_nanfunctions.py26
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()