summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2017-04-28 22:02:48 -0600
committerGitHub <noreply@github.com>2017-04-28 22:02:48 -0600
commitef2cfe12c49ab377cfbf2f54993699b92229b907 (patch)
tree5e1285dd53774d1b158ef9136d2f8956fa285dd8 /numpy
parente87523089129d50428b9a539600899d5c408bbcf (diff)
parenta77709c67051a1d19ed4caa83b0b7686ba22bfc4 (diff)
downloadnumpy-ef2cfe12c49ab377cfbf2f54993699b92229b907.tar.gz
Merge pull request #9013 from eric-wieser/fix-nanfuncs
BUG: Fix np.lib.nanfunctions on object arrays
Diffstat (limited to 'numpy')
-rw-r--r--numpy/lib/nanfunctions.py34
-rw-r--r--numpy/lib/tests/test_nanfunctions.py12
2 files changed, 31 insertions, 15 deletions
diff --git a/numpy/lib/nanfunctions.py b/numpy/lib/nanfunctions.py
index c96e925aa..1e342b932 100644
--- a/numpy/lib/nanfunctions.py
+++ b/numpy/lib/nanfunctions.py
@@ -61,17 +61,19 @@ def _replace_nan(a, val):
NaNs, otherwise return None.
"""
- is_new = not isinstance(a, np.ndarray)
- if is_new:
- a = np.array(a)
- if not issubclass(a.dtype.type, np.inexact):
- return a, None
- if not is_new:
- # need copy
- a = np.array(a, subok=True)
-
- mask = np.isnan(a)
- np.copyto(a, val, where=mask)
+ a = np.array(a, subok=True, copy=True)
+
+ if a.dtype == np.object_:
+ # object arrays do not support `isnan` (gh-9009), so make a guess
+ mask = a != a
+ elif issubclass(a.dtype.type, np.inexact):
+ mask = np.isnan(a)
+ else:
+ mask = None
+
+ if mask is not None:
+ np.copyto(a, val, where=mask)
+
return a, mask
@@ -232,8 +234,9 @@ def nanmin(a, axis=None, out=None, keepdims=np._NoValue):
kwargs = {}
if keepdims is not np._NoValue:
kwargs['keepdims'] = keepdims
- if not isinstance(a, np.ndarray) or type(a) is np.ndarray:
- # Fast, but not safe for subclasses of ndarray
+ if type(a) is np.ndarray and a.dtype != np.object_:
+ # Fast, but not safe for subclasses of ndarray, or object arrays,
+ # which do not implement isnan (gh-9009), or fmin correctly (gh-8975)
res = np.fmin.reduce(a, axis=axis, out=out, **kwargs)
if np.isnan(res).any():
warnings.warn("All-NaN axis encountered", RuntimeWarning, stacklevel=2)
@@ -339,8 +342,9 @@ def nanmax(a, axis=None, out=None, keepdims=np._NoValue):
kwargs = {}
if keepdims is not np._NoValue:
kwargs['keepdims'] = keepdims
- if not isinstance(a, np.ndarray) or type(a) is np.ndarray:
- # Fast, but not safe for subclasses of ndarray
+ if type(a) is np.ndarray and a.dtype != np.object_:
+ # Fast, but not safe for subclasses of ndarray, or object arrays,
+ # which do not implement isnan (gh-9009), or fmax correctly (gh-8975)
res = np.fmax.reduce(a, axis=axis, out=out, **kwargs)
if np.isnan(res).any():
warnings.warn("All-NaN slice encountered", RuntimeWarning, stacklevel=2)
diff --git a/numpy/lib/tests/test_nanfunctions.py b/numpy/lib/tests/test_nanfunctions.py
index 1678e1091..466ceefb5 100644
--- a/numpy/lib/tests/test_nanfunctions.py
+++ b/numpy/lib/tests/test_nanfunctions.py
@@ -152,6 +152,18 @@ class TestNanFunctions_MinMax(TestCase):
assert_(res != np.nan)
assert_(len(w) == 0)
+ def test_object_array(self):
+ arr = np.array([[1.0, 2.0], [np.nan, 4.0], [np.nan, np.nan]], dtype=object)
+ assert_equal(np.nanmin(arr), 1.0)
+ assert_equal(np.nanmin(arr, axis=0), [1.0, 2.0])
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
+ # assert_equal does not work on object arrays of nan
+ assert_equal(list(np.nanmin(arr, axis=1)), [1.0, 4.0, np.nan])
+ assert_(len(w) == 1, 'no warning raised')
+ assert_(issubclass(w[0].category, RuntimeWarning))
+
class TestNanFunctions_ArgminArgmax(TestCase):