[SciPy-dev] problems with amin/amax when nan present

eric eric at enthought.com
Fri Aug 16 02:11:29 CDT 2002


Dave and I just ran across this NaN issue while working on Chaco:

>>> a = array([-1,0,1.])
>>> b = a/0.0
>>> b
array([             -inf,               nan,               inf])
>>> amin(b)
inf

This should be -inf.

>>> c = array((-1,b[1],1))
>>> c
array([-1.        ,         nan,  1.        ])
>>> amin(c)
1.0

This should be -1.

It looks like the NaNs are what cause the problems.  IF only -inf and
inf are present, they behave correctly:

>>> d=b.copy()
>>> d[1] = 0
>>> d
array([             -inf,   0.00000000e+000,               inf])
>>> amin(d)
-inf
>>> amax(d)
inf

So, I've found an ugly fix listed at the end of this message.  It will
make amin/amax slower (probably 2X) even for the case when NaNs aren't
present because it has to test for if any NaNs exists.  Correct is more
important than fast, but I was wondering if anyone has a better
solution.  We could test within the minimum/maximum methods in C using
isnan(), I suppose, to save the extra array creation.

Thanks,
eric

# fix.py
from scipy_base import *

def my_min(a,axis=-1):
    nans = isnan(a)
    has_nans = sometrue(ravel(nans))
    if has_nans:
        inf_in_array = sometrue(a == Inf,axis=axis)
        b = a.copy()
        putmask(b,nans,Inf)
    else:
        b = a
    result = amin(b,axis)   
    if has_nans:
        if type(result) is ArrayType:
            putmask(result,logical_not(
                           logical_and(result == Inf,inf_in_array)),NaN)

        elif (not inf_in_array) and (result == Inf):
            result = NaN            
    return result
    
def my_max(a,axis=-1):
    nans = isnan(a)
    has_nans = sometrue(ravel(nans))
    if has_nans:
        neg_inf_in_array = sometrue(a == -Inf,axis=axis)            
        b = a.copy()
        putmask(b,nans,-Inf)
    else:
        b = a
    result = amax(b,axis)   
    if has_nans:
        if type(result) is ArrayType:
            putmask(result,logical_not(
                        logical_and(result ==
-Inf,neg_inf_in_array)),NaN)   
        elif not(neg_inf_in_array) and (result == -Inf):
            result = NaN            
    return result

a = array((-1.,0.,1.))
print 'a:', a
print 'min(a):', my_min(a)
print 'max(a):', my_max(a)

b = a/0.
print 'b:', b
print 'min(b):', my_min(b)
print 'max(b):', my_max(b)

c = array((0.,0.,0.))/0.
print 'c:', c
print 'min(c):', my_min(c)
print 'max(c):', my_max(c)



# [eric at enthoughtaus1 tmp]$ python fix.py
# a: [-1.  0.  1.]
# min(a): -1.0
# max(a): 1.0
# b: [             -inf               nan               inf]
# min(b): -inf
# max(b): inf
# c: [              nan               nan               nan]
# min(c): nan
# max(c): nan




More information about the Scipy-dev mailing list