Comment puis-je vérifier les valeurs NaN?

982

float('nan')résultats en Nan (pas un nombre). Mais comment puis-je le vérifier? Cela devrait être très facile, mais je ne le trouve pas.

Jack Ha
la source
20
Pour un historique de NaN en Python, voir PEP 754. python.org/dev/peps/pep-0754
Craig McQueen

Réponses:

1284

math.isnan (x)

Retourne Truesi x est un NaN (pas un nombre), et Falsesinon.

>>> import math
>>> x = float('nan')
>>> math.isnan(x)
True
gimel
la source
5
@ charlie-parker: En Python3, math.isnan fait toujours partie du module mathématique. docs.python.org/3/library/math.html#math.isnan . Utilisez numpy.isnan si vous le souhaitez, cette réponse n'est qu'une suggestion.
gimel
2
@ SittingBull Voir docs.python.org/3/library/functions.html#float "Si l'argument est une chaîne, il doit contenir un nombre décimal", ou "Infinity" "inf" "nan"
gimel
35
est math.isnanpréféré à np.isnan()?
TMWP
34
@TMWP peut-être ... import numpyprend environ 15 Mo de RAM, alors qu'il en import mathfaut environ 0,2 Mo
petrpulc
9
@TMWP: Si vous utilisez NumPy, numpy.isnanc'est un choix supérieur, car il gère les tableaux NumPy. Si vous n'utilisez pas NumPy, il n'y a aucun avantage à prendre une dépendance NumPy et à passer du temps à charger NumPy juste pour une vérification NaN (mais si vous écrivez le type de code qui fait des vérifications NaN, il est probable que vous devriez utiliser NumPy).
user2357112 prend en charge Monica
360

La façon habituelle de tester un NaN est de voir s'il est égal à lui-même:

def isNaN(num):
    return num != num
Chris Jester-Young
la source
8
Mot d'avertissement: citant le commentaire de Bear ci-dessous "Pour les personnes coincées avec python <= 2,5. Nan! = Nan ne fonctionnait pas de manière fiable. Utilisé numpy à la place." Cela dit, je ne l'ai jamais vu échouer.
mavnn
22
Je suis sûr que, compte tenu de la surcharge de l'opérateur, il existe de nombreuses façons de confondre cette fonction. rendez-vous avec math.isnan ()
djsadinoff
4
Il est dit dans la spécification 754 mentionnée ci-dessus que NaN == NaN doit toujours être faux, bien qu'il ne soit pas toujours implémenté en tant que tel. N'est-il pas possible que c'est ainsi que les mathématiques et / ou numpy vérifient cela sous le capot?
Hari Ganesan
Merci . c'est également 15 à 20 fois plus rapide que d'utiliser np.isnan si vous effectuez une opération sur un scalaire
thomas.mac
5
Même si cela fonctionne et, dans une certaine mesure, est logique, je suis un humain avec des principes et je déclare par la présente que la sorcellerie est interdite. Veuillez utiliser math.isnan à la place.
Gonzalo
152

numpy.isnan(number)vous dit si c'est le cas NaNou non.

mavnn
la source
3
Fonctionne également en python version 2.7.
Michel Keijzers
6
numpy.all(numpy.isnan(data_list))est également utile si vous devez déterminer si tous les éléments de la liste sont nan
Jay P.
3
Pas besoin de NumPy:all(map(math.isnan, [float("nan")]*5))
sleblanc
6
Lorsque cette réponse a été écrite il y a 6 ans, Python 2.5 était encore couramment utilisé - et math.isnan ne faisait pas partie de la bibliothèque standard. De nos jours, j'espère vraiment que ce n'est pas le cas dans de nombreux endroits!
2015
4
notez que np.isnan () ne gère pas le type decimal.Decimal (autant de fonctions de numpy). math.isnan () gère.
comte
55

Voici trois façons de tester ou non une variable "NaN".

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)}")

Production

It's pd.isna  : True
It's np.isnan  : True
It's math.isnan  : True
M. Hamza Rajput
la source
2
pd.isna (valeur) a sauvé beaucoup de problèmes! travailler comme un charme!
abhishake
1
ps.isna()résout mes problèmes. Merci!
darthbhyrava
32

voici une réponse avec:

  • Implémentations NaN respectant la norme IEEE 754
    • à savoir: NaN python: float('nan'), numpy.nan...
  • tout autre objet: chaîne ou autre (ne déclenche pas d'exceptions s'il est rencontré)

Un NaN implémenté suivant la norme, est la seule valeur pour laquelle la comparaison des inégalités avec lui-même doit retourner True:

def is_nan(x):
    return (x != x)

Et quelques exemples:

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)}")

Production:

nan      : True
nan      : True
55       : False
'string' : False
<function <lambda> at 0x000000000927BF28> : False
x0s
la source
1
La série que je vérifie est que les chaînes avec des valeurs manquantes sont «nans» (???), donc cette solution fonctionne là où d'autres ont échoué.
keithpjolley
numpy.nanest un floatobjet Python standard , tout comme le type retourné par float('nan'). La plupart des NaN que vous rencontrez dans NumPy ne seront pas l' numpy.nanobjet.
user2357112 prend en charge Monica
numpy.nandéfinit sa valeur NaN sur sa propre dans la bibliothèque sous - jacente en C . Il n'emballe pas le NaN de python. Mais maintenant, ils sont tous deux conformes à la norme IEEE 754 car ils s'appuient sur l'API C99.
7h59
@ user2357112supportsMonica: Python et numpy NaN ne se comportent pas en fait de la même manière: float('nan') is float('nan')(non unique) et np.nan is np.nan(unique)
x0s
@ x0s: Cela n'a rien à voir avec NumPy. np.nanest un objet spécifique, tandis que chaque float('nan')appel produit un nouvel objet. Si vous le faisiez nan = float('nan'), vous en auriez nan is nanaussi. Si vous construisiez un véritable NumPy NaN avec quelque chose comme ça np.float64('nan'), vous en auriez np.float64('nan') is not np.float64('nan')aussi .
user2357112 prend en charge Monica
28

En fait, je suis juste tombé sur cela, mais pour moi, il vérifiait nan, -inf ou inf. Je viens d'utiliser

if float('-inf') < float(num) < float('inf'):

Cela est vrai pour les nombres, faux pour nan et les deux inf, et soulèvera une exception pour des choses comme les chaînes ou d'autres types (ce qui est probablement une bonne chose). De plus, cela ne nécessite pas d'importer de bibliothèques comme math ou numpy (numpy est tellement gros qu'il double la taille de toute application compilée).

DaveTheScientist
la source
9
math.isfiniten'a pas été introduit avant Python 3.2, donc étant donné la réponse de @DaveTheScientist publiée en 2012, ce n'était pas exactement "réinventer [la roue]" - la solution représente toujours ceux qui travaillent avec Python 2.
sudo_coffee
22

math.isnan ()

ou comparer le nombre à lui-même. NaN est toujours! = NaN, sinon (par exemple s'il s'agit d' un nombre) la comparaison doit réussir.

Tomalak
la source
6
Pour les personnes coincées avec python <= 2,5. Nan! = Nan n'a pas fonctionné de manière fiable. Utilisé numpy à la place.
Gardez le
16

Une autre méthode si vous êtes bloqué sur <2.6, vous n'avez pas numpy et vous n'avez pas de support IEEE 754:

def isNaN(x):
    return str(x) == str(1e400*0)
Josh Lee
la source
12

Eh bien, je suis entré dans ce message, car j'ai eu quelques problèmes avec la fonction:

math.isnan()

Il y a un problème lorsque vous exécutez ce code:

a = "hello"
math.isnan(a)

Cela soulève une exception. Ma solution est de faire une autre vérification:

def is_nan(x):
    return isinstance(x, float) and math.isnan(x)
Idok
la source
3
Il a probablement été rejeté car isnan () prend un flottant, pas une chaîne. Il n'y a rien de mal avec la fonction, et les problèmes ne résident que dans sa tentative d'utilisation. (Pour ce cas d'utilisation particulier, sa solution est valide, mais ce n'est pas une réponse à cette question.)
Peter Hansen
6
Soyez prudent lorsque vous vérifiez les types de cette manière. Cela ne fonctionnera pas, par exemple pour les NaP numpy.float32. Mieux vaut utiliser une construction try / except: def is_nan(x): try: return math.isnan(x) except: return False
Rob
3
NaN ne signifie pas qu'une valeur n'est pas un nombre valide. Cela fait partie de la représentation en virgule flottante IEEE pour spécifier qu'un résultat particulier n'est pas défini. par exemple 0/0. Par conséquent, demander si "bonjour" est nan n'a pas de sens.
Brice M. Dempsey
2
c'est mieux parce que NaN peut atterrir dans n'importe quelle liste de chaînes, entiers ou flottants, donc vérification utile
RAFIQ
J'ai dû implémenter exactement cela pour gérer les colonnes de chaînes dans les pandas.
Cristian Garcia
7

Avec python <2.6, je me suis retrouvé avec

def isNaN(x):
    return str(float(x)).lower() == 'nan'

Cela fonctionne pour moi avec python 2.5.1 sur une boîte Solaris 5.9 et avec python 2.6.5 sur Ubuntu 10

Mauro Bianchi
la source
6
Ce n'est pas trop portable, comme Windows l'appelle parfois-1.#IND
Mike T
5

Je reçois les données d'un service Web qui envoie NaNsous forme de chaîne 'Nan'. Mais il pourrait y avoir d'autres types de chaînes dans mes données, donc un simple float(value)pourrait lever une exception. J'ai utilisé la variante suivante de la réponse acceptée:

def isnan(value):
  try:
      import math
      return math.isnan(float(value))
  except:
      return False

Exigence:

isnan('hello') == False
isnan('NaN') == True
isnan(100) == False
isnan(float('nan')) = True
Mahdi
la source
1
outry: int(value)
chwi
@chwi alors que dit votre suggestion sur le fait d' valueêtre NaNou non?
Mahdi
Eh bien, étant "pas un nombre", tout ce qui ne peut pas être converti en un entier, je suppose, n'est en fait pas un nombre, et l'instruction try échouera? Essayez, retournez vrai, sauf retour faux.
chwi
@chwi Eh bien, en prenant "pas un nombre" littéralement, vous avez raison, mais ce n'est pas le point ici. En fait, je cherche exactement ce qu'est la sémantique NaN(comme en python ce que vous pourriez obtenir float('inf') * 0), et donc bien que la chaîne 'Hello' ne soit pas un nombre, mais ce n'est pas non plus NaNparce que NaNc'est toujours une valeur numérique!
Mahdi
@chwi: Vous avez raison, si la gestion des exceptions concerne une exception spécifique. Mais dans cette réponse, une exception générique a été gérée. Donc pas besoin de vérifier int(value)Pour toutes les exceptions, Falsesera écrit.
Harsha Biyani
3

Toutes les méthodes pour savoir si la variable est NaN ou None:

Aucun 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()

Type NaN

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
siberiawolf61
la source
2

Comment supprimer des éléments NaN (float) d'une liste de types de données mixtes

Si vous avez des types mixtes dans un itérable, voici une solution qui n'utilise pas 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]

L'évaluation de court-circuit signifie que isnanles valeurs qui ne sont pas de type «flottant» ne seront pas appelées, car elles False and (…)sont évaluées rapidement Falsesans avoir à évaluer le côté droit.

sleblanc
la source
1

En Python 3.6, la vérification d'une valeur de chaîne x math.isnan (x) et np.isnan (x) déclenche une erreur. Je ne peux donc pas vérifier si la valeur donnée est NaN ou non si je ne sais pas au préalable que c'est un nombre. Ce qui suit semble résoudre ce problème

if str(x)=='nan' and type(x)!='str':
    print ('NaN')
else:
    print ('non NaN')
Valentin Goikhman
la source
1

Il semble que vérifier s'il est égal à lui-même

x!=x

est le plus rapide.

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)
Grzegorz
la source
0

Pour nan de type flotteur

>>> 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
J11
la source
-5

pour les chaînes en panda, prenez pd.isnull:

if not pd.isnull(atext):
  for word in nltk.word_tokenize(atext):

la fonction d'extraction de fonctionnalités pour 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
Max Kleiner
la source
Que pour cette réduction?
Max Kleiner
isnull renvoie true pour non seulement les valeurs NaN.
Boris