简体   繁体   中英

Why is `NaN` considered “smaller” than `-np.inf` in numpy?

What is the reason that NaN 's are considered less than -np.inf in any comparisons involving np.min or np.argmin ?

import numpy as np
In [73]: m = np.array([np.nan, 1., 0., -np.inf])
In [74]: n = np.array([-np.inf, 1., 0., np.nan])

# Huh??
In [75]: np.min(m)
Out[75]: nan
In [76]: np.min(n)
Out[76]: nan

# Same for np.argmin
In [77]: np.argmin(m)
Out[77]: 0
In [78]: np.argmin(n)
Out[78]: 3

# Its all false!
In [79]: np.nan < -np.inf
Out[79]: False

In [80]: np.nan > -np.inf
Out[80]: False

# OK, that seems to fix it, but its not necessarily elegant
In [81]: np.nanmin(m)
Out[81]: -inf

In [82]: np.nanargmin(m)
Out[82]: 3

I would guess that its probably a side effect of any comparisons with NaN values returning False , however this imho leads to some rather annoying effects when you "happen" to sometimes end up with a NaN value in your array. The usage of np.nanmin or np.nanargmin some feels like a quickfix that was somehow stapled on top of the existing behaviour.

Apart from that note in the docs : " NaN values are propagated, that is if at least one item is NaN, the corresponding min value will be NaN as well. To ignore NaN values (MATLAB behavior), please use nanmin. , I haven't found anything that explains the rationale behind that behaviour. Is this wanted or a side effect of a particular internal representation of NaN values? And why?

As @Dunno mentioned in a comment, it does not give much meaning to compare a NaN with a number, so this behaviour is probably ok. The IEEE 754 standard says this about comparing NaNs with numbers:

Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself

According to the standard this:

# Its all false!
In [79]: np.nan < -np.inf
Out[79]: False

would result in an "unordered" result, so it is not true that it is belongs to the relation "less than".

So, as you might be already knowing this:-

" inf " is infinity - a value that is greater than any other value. " -inf " is, therefore, smaller than any other value remember this value is a number.

" nan " stands for Not A Number.

So, if according to your array " m,n " as you declared above and as soon as you perform " np.min() " on any of these actually what happens is as soon as " nan " is encountered the other elements are not checked or compared and the following statement is executed and the value is returned:

 if (@isnan@(mp)) { /* nan encountered; it's maximal */ return 0; } 

and thus a " nan " is returned as the answer to the function!

Check this code it returns as soon as it encounter's first " nan " and its position is returned in the corresponding function

    In [1]: import numpy as np

    In [2]: m = np.array([1., 0., -np.inf, np.nan])

    In [3]: n = np.array([np.nan, 1., np.nan, 0.])

    In [4]: np.argmin(m)
    Out[4]: 3

    In [5]: np.argmin(n)
    Out[5]: 0

and the operation's such as " np.nan < -np.inf " and " np.nan > -np.inf " returns " False " because " nan " cannot be compared by any number " -inf " here and the " False " in each case of above operation is not the answer of comparison but is because of a kind of exception or the execution of the code mentioned above which is due to logical error because though infinity but it cannot be compared to a thing " nothing " with respect to a number!

and therefore if you remove all " nan " in the array and then calculate min by " np.nanmin() " you get the output as expected " -inf " here no problem arises!

So," Nan "is not smaller or greater than " inf " or " -inf " because actually it is not comparable with any of these or any number it will return " False " in comparison with any number !!

    In [1]: np.nan < 1
    Out[1]: False

    In [2]: np.nan > 1
    Out[2]: False

and so on ...............

Hope it helps !!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM