[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