简体   繁体   中英

How to check for float('nan') in Python?

In some data I am processing I am encountering data of the type float , which are filled with 'nan', ie float('nan') .

However checking for it does not work as expected:

float('nan') == float('nan')
>> False

You can check it with math.isnan , but as my data also contains strings (For example: 'nan', but also other user input), it is not that convenient:

import math
math.isnan(float('nan'))
>> True
math.isnan('nan')
>> TypeError: must be real number, not str

In the ideal world I would like to check if a value is in a list of all possible NaN values, for example:

import numpy as np
if x in ['nan', np.nan, ... ]:
    # Do something
    pass

Now the question: How can I still use this approach but also check for float('nan') values? And why equals float('nan') == float('nan') False

It's very pedestrian, and a bit ugly, but why not just do the following?

import math
import numpy as np

if math.isnan(x) or x in ['nan', np.nan, ... ]:
    # Do something
    pass

I want to recommend a Yoda expression but haven't quite worked it out yet.

If you want to sweep everything under the carpet put it in a lambda or function.

Following on from https://stackoverflow.com/a/64090763/1021819 , you can try to get the iterator to evaluate any in a lazy fashion. The problem then is that if none of the first conditions evaluates to True then the math.isnan() call is executed and can still throw the TypeError . If you evaluate lazily you can guard the math.isnan() call with a type check against str :

fn_list_to_check=[
    lambda x: x in ['nan', np.nan, ... ],
    lambda x: not isinstance(x, str),
    lambda x: math.isnan(x)
    ]

if any(f(x) for f in fn_list_to_check):
    # Do something
    pass

Note the absence of square list brackets in the any ie any() not any([]) (who knew?).

I think it's quite brilliant but equally as ugly - choose your poison.

For the second part of the question (why float('nan') != float('nan') ), see

What is the rationale for all comparisons returning false for IEEE754 NaN values?

Why not just wrap whatever you pass to math.isnan with another float conversion? If it was already a float (ie float('nan') ) you just made a "redundant" call:

import math

def is_nan(value):
    return math.isnan(float(value))

And this seems to give your expected results:

>>> is_nan(float('nan'))
True
>>> is_nan('nan')
True
>>> is_nan(np.nan)
True

You can check for NaN value like this,

def isNaN(num):
    return num!= num

NaN represents as 'Not A Number'

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