Reputation: 20951
float('nan')
represents NaN (not a number). But how do I check for it?
Upvotes: 1703
Views: 3066926
Reputation: 269
Here it is 2024 and I've been struggling with this. What I found, based on all the suggestions and comments above:
numpy returns nan for blank excel spreadsheet cells. nan is a float.
To test for this,
if type(activity) == float and np.isnan(activity):
It also works fine with math.isnan()
.
You can't use isnan unless you first test for float since running either math.isnan
or numpy.isnan
on another type (like str) will throw an error.
Upvotes: 1
Reputation: 1353
Editor's note: The below timings are flawed, for example, they have not factored out name lookup time. See the comments.
It seems that checking if it's equal to itself (x != x
) is the fastest.
import pandas as pd
import numpy as np
import math
x = float('nan')
%timeit x != x
44.8 ns ± 0.152 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit math.isnan(x)
94.2 ns ± 0.955 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit pd.isna(x)
281 ns ± 5.48 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit np.isnan(x)
1.38 µs ± 15.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Upvotes: 63
Reputation: 2091
To filter out both empty strings (''
), None and NaN
values in the 'num_specimen_seen' column, we can use the pd.notna()
function from pandas.
import pandas as pd
import numpy as np
df = pd.DataFrame({
'num_specimen_seen': [10, 2, 1, '', 34, 'aw', np.NaN, 5, '43', np.nan, 'ed', None, '']
})
for idx, row in df.iterrows():
if pd.notna(row['num_specimen_seen']) and row['num_specimen_seen'] != '':
print(idx, row['num_specimen_seen'])
This code will skip both NaN
and empty strings in the 'num_specimen_seen' column when iterating over the DataFrame.
Upvotes: 0
Reputation: 10216
Here are three ways where you can test a variable is "NaN" or not.
import pandas as pd
import numpy as np
import math
# For single variable all three libraries return single boolean
x1 = float("nan")
print(f"It's pd.isna: {pd.isna(x1)}")
print(f"It's np.isnan: {np.isnan(x1)}}")
print(f"It's math.isnan: {math.isnan(x1)}}")
Output:
It's pd.isna: True
It's np.isnan: True
It's math.isnan: True
Upvotes: 259
Reputation: 23011
If you want to check for values that are not NaN, then negate whatever is used to flag NaNs; pandas has its own dedicated function for flagging non-NaN values.
lst = [1, 2, float('nan')]
m1 = [e == e for e in lst] # [True, True, False]
m2 = [not math.isnan(e) for e in lst] # [True, True, False]
m3 = ~np.isnan(lst) # array([ True, True, False])
m4 = pd.notna(lst) # array([ True, True, False])
This is especially useful if you want to filter values that are not NaN. For ndarray/Series objects, ==
is vectorized, so it can be used as well.
s = pd.Series(lst)
arr = np.array(lst)
x = s[s.notna()]
y = s[s==s] # `==` is vectorized
z = arr[~np.isnan(arr)] # array([1., 2.])
assert (x == y).all() and (x == z).all()
Upvotes: 0
Reputation: 86344
Use math.isnan
:
>>> import math
>>> x = float('nan')
>>> math.isnan(x)
True
Upvotes: 2177
Reputation: 3921
How to remove NaN (float) item(s) from a list of mixed data types
If you have mixed types in an iterable, here is a solution that does not use numpy:
from math import isnan
Z = ['a','b', float('NaN'), 'd', float('1.1024')]
[x for x in Z if not (
type(x) == float # let's drop all float values…
and isnan(x) # … but only if they are nan
)]
['a', 'b', 'd', 1.1024]
Short-circuit evaluation means that isnan
will not be called on values that are not of type 'float', as False and (…)
quickly evaluates to False
without having to evaluate the right-hand side.
Upvotes: 4
Reputation: 42886
Comparison pd.isna
, math.isnan
and np.isnan
and their flexibility dealing with different type of objects.
The table below shows if the type of object can be checked with the given method:
+------------+-----+---------+------+--------+------+
| Method | NaN | numeric | None | string | list |
+------------+-----+---------+------+--------+------+
| pd.isna | yes | yes | yes | yes | yes |
| math.isnan | yes | yes | no | no | no |
| np.isnan | yes | yes | no | no | yes | <-- # will error on mixed type list
+------------+-----+---------+------+--------+------+
pd.isna
The most flexible method to check for different types of missing values.
None of the answers cover the flexibility of pd.isna
. While math.isnan
and np.isnan
will return True
for NaN
values, you cannot check for different type of objects like None
or strings. Both methods will return an error, so checking a list with mixed types will be cumbersom. This while pd.isna
is flexible and will return the correct boolean for different kind of types:
In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: missing_values = [3, None, np.NaN, pd.NA, pd.NaT, '10']
In [4]: pd.isna(missing_values)
Out[4]: array([False, True, True, True, True, False])
Upvotes: 12
Reputation: 1868
here is an answer working with:
float('nan')
, numpy.nan
...A NaN implemented following the standard, is the only value for which the inequality comparison with itself should return True:
def is_nan(x):
return (x != x)
And some examples:
import numpy as np
values = [float('nan'), np.nan, 55, "string", lambda x : x]
for value in values:
print(f"{repr(value):<8} : {is_nan(value)}")
Output:
nan : True
nan : True
55 : False
'string' : False
<function <lambda> at 0x000000000927BF28> : False
Upvotes: 49
Reputation: 115
In Python 3.6 checking on a string value x math.isnan(x) and np.isnan(x) raises an error. So I can't check if the given value is NaN or not if I don't know beforehand it's a number. The following seems to solve this issue
if str(x)=='nan' and type(x)!='str':
print ('NaN')
else:
print ('non NaN')
Upvotes: 4
Reputation: 1612
for strings in panda take pd.isnull:
if not pd.isnull(atext):
for word in nltk.word_tokenize(atext):
the function as feature extraction for NLTK
def act_features(atext):
features = {}
if not pd.isnull(atext):
for word in nltk.word_tokenize(atext):
if word not in default_stopwords:
features['cont({})'.format(word.lower())]=True
return features
Upvotes: -5
Reputation: 465
For nan of type float
>>> import pandas as pd
>>> value = float(nan)
>>> type(value)
>>> <class 'float'>
>>> pd.isnull(value)
True
>>>
>>> value = 'nan'
>>> type(value)
>>> <class 'str'>
>>> pd.isnull(value)
False
Upvotes: 1
Reputation: 77
All the methods to tell if the variable is NaN or None:
None type
In [1]: from numpy import math
In [2]: a = None
In [3]: not a
Out[3]: True
In [4]: len(a or ()) == 0
Out[4]: True
In [5]: a == None
Out[5]: True
In [6]: a is None
Out[6]: True
In [7]: a != a
Out[7]: False
In [9]: math.isnan(a)
Traceback (most recent call last):
File "<ipython-input-9-6d4d8c26d370>", line 1, in <module>
math.isnan(a)
TypeError: a float is required
In [10]: len(a) == 0
Traceback (most recent call last):
File "<ipython-input-10-65b72372873e>", line 1, in <module>
len(a) == 0
TypeError: object of type 'NoneType' has no len()
NaN type
In [11]: b = float('nan')
In [12]: b
Out[12]: nan
In [13]: not b
Out[13]: False
In [14]: b != b
Out[14]: True
In [15]: math.isnan(b)
Out[15]: True
Upvotes: 4
Reputation: 1852
I am receiving the data from a web-service that sends NaN
as a string 'Nan'
. But there could be other sorts of string in my data as well, so a simple float(value)
could throw an exception. I used the following variant of the accepted answer:
def isnan(value):
try:
import math
return math.isnan(float(value))
except:
return False
Requirement:
isnan('hello') == False
isnan('NaN') == True
isnan(100) == False
isnan(float('nan')) = True
Upvotes: 7
Reputation: 3399
I actually just ran into this, but for me it was checking for nan, -inf, or inf. I just used
if float('-inf') < float(num) < float('inf'):
This is true for numbers, false for nan and both inf, and will raise an exception for things like strings or other types (which is probably a good thing). Also this does not require importing any libraries like math or numpy (numpy is so damn big it doubles the size of any compiled application).
Upvotes: 33
Reputation: 4132
Well I entered this post, because i've had some issues with the function:
math.isnan()
There are problem when you run this code:
a = "hello"
math.isnan(a)
It raises exception. My solution for that is to make another check:
def is_nan(x):
return isinstance(x, float) and math.isnan(x)
Upvotes: 27
Reputation: 693
With python < 2.6 I ended up with
def isNaN(x):
return str(float(x)).lower() == 'nan'
This works for me with python 2.5.1 on a Solaris 5.9 box and with python 2.6.5 on Ubuntu 10
Upvotes: 10
Reputation: 177500
Another method if you're stuck on <2.6, you don't have numpy, and you don't have IEEE 754 support:
def isNaN(x):
return str(x) == str(1e400*0)
Upvotes: 17
Reputation: 338108
or compare the number to itself. NaN is always != NaN, otherwise (e.g. if it is a number) the comparison should succeed.
Upvotes: 29
Reputation: 222973
The usual way to test for a NaN is to see if it's equal to itself:
def isNaN(num):
return num != num
Upvotes: 618