¿Cómo puedo verificar los valores de NaN?

1284

float('nan')da como resultado Nan (no un número). Pero, ¿cómo lo compruebo? Debería ser muy fácil, pero no puedo encontrarlo.

1
1654

matemáticas.isnan (x)

Return True if x is a NaN (not a number), and False otherwise.

>>> import math
>>> x = float('nan')
>>> math.isnan(x)
True
17
  • 8
    @ charlie-parker: En Python3, math.isnan sigue siendo parte del módulo de matemáticas. docs.python.org/3/library/math.html#math.isnan . Use numpy.isnan si lo desea, esta respuesta es solo una sugerencia. gimel 8 de septiembre de 2016 a las 4:43
  • 59
    se math.isnanprefiere a np.isnan()? TMWP 1 de agosto de 2017 a las 2:25
  • 57
    @TMWP posiblemente ... import numpytoma alrededor de 15 MB de RAM, mientras que import mathtoma alrededor de 0,2 MBpetrpulc 12 sep 2017 a las 12:09
  • 24
    @TMWP: si está utilizando NumPy, numpy.isnanes una opción superior, ya que maneja matrices NumPy. Si no está usando NumPy, no hay ningún beneficio en tomar una dependencia de NumPy y dedicar el tiempo a cargar NumPy solo para una verificación de NaN (pero si está escribiendo el tipo de código que realiza verificaciones de NaN, es probable que deba usar NumPy). user2357112 supports Monica 21 feb 2019 a las 0:51
  • 4
    @jungwook Eso en realidad no funciona. Tu expresión siempre es falsa. Es decir, float('nan') == float('nan')devoluciones False, que es una convención extraña, pero básicamente parte de la definición de NaN. El enfoque que desea es en realidad el publicado por Chris Jester-Young, a continuación. Mike 11/07/19 a las 15:38
463

La forma habitual de probar un NaN es ver si es igual a sí mismo:

def isNaN(num):
    return num != num
11
  • 8
    Advertencia: citando el comentario de Bear a continuación "Para las personas que se han quedado con Python <= 2.5. ¡Nan! = Nan no funcionó de manera confiable. Se usó numpy en su lugar". Habiendo dicho eso, en realidad nunca lo he visto fallar. mavnn 26/01/10 a las 13:18
  • 34
    Estoy seguro de que, dada la sobrecarga del operador, hay muchas formas en las que podría confundir esta función. ir con math.isnan ()djsadinoff 11/08/11 a las 22:38
  • 5
    Dice en la especificación 754 mencionada anteriormente que NaN == NaN siempre debe ser falso, aunque no siempre se implementa como tal. ¿No es posible que así sea como las matemáticas y / o numpy comprueban esto bajo el capó de todos modos? Hari Ganesan 1/04/2014 a las 16:16
  • 19
    Aunque esto funciona y, hasta cierto punto, tiene sentido, soy un ser humano con principios y por la presente declaro que esto es brujería prohibida. Utilice math.isnan en su lugar. Gonzalo 16/10/19 a las 21:09
  • 4
    @djsadinoff ¿Hay algún otro inconveniente en la confusión? math.isnan () no puede verificar valores de cadena, por lo que esta solución parece más robusta. William Torkington 28 de mayo de 2020 a las 10:11
214

numpy.isnan(number)te dice si lo es NaNo no.

9
  • 3
    También funciona en la versión 2.7 de Python. Michel Keijzers 5/12/12 a las 14:35
  • 6
    numpy.all(numpy.isnan(data_list))también es útil si necesita determinar si todos los elementos de la lista son nanJay P. 27/0214 a las 22:18
  • 4
    Sin necesidad de NumPy:all(map(math.isnan, [float("nan")]*5))sleblanc 28 de marzo de 2015 a las 3:41
  • 7
    Cuando se escribió esta respuesta hace 6 años, Python 2.5 todavía era de uso común, y math.isnan no formaba parte de la biblioteca estándar. ¡Hoy en día realmente espero que ese no sea el caso en muchos lugares! mavnn 30 de marzo de 2015 a las 7:30
  • 4
    tenga en cuenta que np.isnan () no maneja el tipo decimal.Decimal (la función de muchos numpy). math.isnan () maneja. comte 16 de mayo de 2018 a las 15:53
144

Aquí hay tres formas en las que puede probar si una variable es "NaN" o no.

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

Producción

It's pd.isna: True
It's np.isnan: True
It's math.isnan: True
4
  • 9
    ¡pd.isna (valor facial) salvó muchos problemas! trabajando como un encanto! abhishake 15/10/19 a las 16:57
  • 2
    pd.isnan()o pd.isna()? Esa es la pregunta: Dmah65 13 abr a las 14:44
  • 1
    la versión 3 de esta respuesta era correcta y estaba bien formateada. este (ahora 7) está mal de nuevo. revertido como "no quiero su edición" mientras que las ediciones mejoraron la respuesta, wtf. jemand771 20 de mayo a las 13:52
  • gracias respuesta ha sido actualizadaM. Hamza Rajput 25 de mayo a las 10:05 p.m.
46

aquí hay una respuesta que trabaja con:

  • Implementaciones NaN respetando el estándar IEEE 754
    • es decir: de pitón de: float('nan'), numpy.nan...
  • cualquier otro objeto: cadena o lo que sea (no genera excepciones si se encuentra)

Un NaN implementado siguiendo el estándar, es el único valor para el cual la comparación de desigualdad consigo misma debe devolver True:

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

Y algunos ejemplos:

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

Producción:

nan      : True
nan      : True
55       : False
'string' : False
<function <lambda> at 0x000000000927BF28> : False
8
  • 1
    La serie que estoy comprobando es que las cadenas con valores faltantes son 'nans' (???), por lo que esta solución funciona donde otras fallaron. keithpjolley 3/11/18 a las 22:49
  • numpy.nanes un floatobjeto Python normal , al igual que el tipo devuelto por float('nan'). La mayoría de los NaN que encuentre en NumPy no serán el numpy.nanobjeto. user2357112 supports Monica 14 abr.20 a las 7:13
  • numpy.nandefine su valor NaN por sí solo en la biblioteca subyacente en C . No envuelve el NaN de Python. Pero ahora, ambos cumplen con el estándar IEEE 754 ya que dependen de la API C99. x0s 22 abr.20 a las 7:59
  • @ user2357112supportsMonica: Python y numpy NaN en realidad no se comportan de la misma manera: float('nan') is float('nan')(no único) y np.nan is np.nan(único)x0s 22 abr.20 a las 8:07
  • @ x0s: Eso no tiene nada que ver con NumPy. np.nanes un objeto específico, mientras que cada float('nan')llamada produce un nuevo objeto. Si lo nan = float('nan')hicieras, nan is nantambién lo harías . Si has construido un real NumPy NaN con algo así como np.float64('nan'), a continuación, se obtendría np.float64('nan') is not np.float64('nan')demasiado . user2357112 supports Monica 22 abr.20 a las 10:09
33

De hecho, me encontré con esto, pero para mí estaba comprobando nan, -inf o inf. Acabo de usar

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

Esto es cierto para los números, falso para nan y ambos inf, y generará una excepción para cosas como cadenas u otros tipos (lo que probablemente sea algo bueno). Además, esto no requiere importar ninguna biblioteca como math o numpy (numpy es tan malditamente grande que duplica el tamaño de cualquier aplicación compilada).

2
  • 12
    math.isfiniteno se introdujo hasta Python 3.2, por lo que, dada la respuesta de @DaveTheScientist publicada en 2012, no fue exactamente "reinventar [ing] la rueda"; la solución sigue siendo válida para aquellos que trabajan con Python 2.sudo_coffee 22/11/2016 a las 17:09
  • Esto puede resultar útil para las personas que necesiten comprobar la presencia de NaN en una pd.evalexpresión. Por ejemplo pd.eval(float('-inf') < float('nan') < float('inf')), volveráFalseDerek O 25 de mayo a las 15:33
31

Parece que comprobar si es igual a sí mismo

x!=x

es el más rápido.

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)

2
  • Vale la pena señalar que esto funciona incluso si se cuestionan los infinitos. Es decir, si z = float('inf'), z != zcomo resultado false. npengra317 30 oct.20 a las 19:05
  • en mi computadora z=float('inf')y luego z==zdar True. x=float('nan')y luego x==xdar Falso. matan h 10/12/20 a las 13:40
26

math.isnan ()

o compare el número consigo mismo. NaN es siempre! = NaN, de lo contrario (por ejemplo, si es un número) la comparación debería tener éxito.

1
  • 6
    Para personas atrapadas con Python <= 2.5. Nan! = Nan no funcionó de manera confiable. Usado numpy en su lugar. Bear 18 de enero de 2010 a las 7:06
18

Bueno, entré a esta publicación porque he tenido algunos problemas con la función:

math.isnan()

Hay un problema al ejecutar este código:

a = "hello"
math.isnan(a)

Plantea excepción. Mi solución para eso es hacer otra verificación:

def is_nan(x):
    return isinstance(x, float) and math.isnan(x)
5
  • 4
    Probablemente se votó negativamente porque isnan () toma un flotador, no una cadena. No hay nada de malo en la función, y los problemas están solo en su intento de usarla. (Para ese caso de uso particular, su solución es válida, pero no es una respuesta a esta pregunta)Peter Hansen 07/07/2013 a las 14:12
  • 6
    Tenga cuidado al verificar los tipos de esta manera. Esto no funcionará, por ejemplo, para numpy.float32 NaN. Es mejor usar una construcción try / except: def is_nan(x): try: return math.isnan(x) except: return FalseRob 24 mar 2014 a las 10:25
  • 3
    NaN no significa que un valor no sea un número válido. Es parte de la representación de punto flotante IEEE especificar que un resultado en particular no está definido. por ejemplo, 0 / 0. Por lo tanto, preguntar si "hola" es nan no tiene sentido. Brice M. Dempsey 17 de julio de 2015 a las 8:50
  • 2
    esto es mejor porque NaN puede aterrizar en cualquier lista de cadenas, entradas o flotantes, así que verificación útilRAFIQ 11/03/2016 a las 8:41
  • Tuve que implementar exactamente esto para manejar columnas de cadenas en pandas. Cristian Garcia 4 jun 20 a las 19:09
17

Otro método si está atascado en <2.6, no tiene numpy y no tiene soporte para IEEE 754:

def isNaN(x):
    return str(x) == str(1e400*0)
0
10

Con python <2.6 terminé con

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

Esto me funciona con python 2.5.1 en una caja de Solaris 5.9 y con python 2.6.5 en Ubuntu 10

1
  • 6
    Esto no es demasiado portátil, como Windows a veces lo llama-1.#INDMike T 1 de febrero de 2012 a las 12:54
6

Recibo los datos de un servicio web que los envía NaNcomo una cadena 'Nan'. Pero también podría haber otros tipos de cadenas en mis datos, por lo que un simple float(value)podría generar una excepción. Usé la siguiente variante de la respuesta aceptada:

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

Requisito:

isnan('hello') == False
isnan('NaN') == True
isnan(100) == False
isnan(float('nan')) = True
5
  • 1
    otry: int(value)chwi 6 de julio de 2016 a las 14:00
  • @chwi entonces, ¿qué dice tu sugerencia sobre valueser NaNo no? Mahdi 6 de julio de 2016 a las 15:39
  • Bueno, al ser "no un número", cualquier cosa que no se pueda convertir en un int supongo que de hecho no es un número, y la sentencia try fallará. Intente, devuelva verdadero, excepto que devuelva falso. chwi 7 de julio de 2016 a las 9:29
  • @chwi Bueno, tomando literalmente "no un número", tienes razón, pero ese no es el punto aquí. De hecho, estoy buscando exactamente cuál es la semántica de NaN(como en Python, de lo que podría obtener float('inf') * 0) y, por lo tanto, aunque la cadena 'Hola' no es un número, ¡tampoco lo es NaNporque NaNsigue siendo un valor numérico! Mahdi 7/07/2016 a las 11:19
  • @chwi: Tiene razón, si el manejo de excepciones es para una excepción específica. Pero en esta respuesta, se han manejado excepciones genéricas. Por lo tanto, no es necesario marcar int(value)Para todas las excepciones, Falsese escribirán. Harsha Biyani 15/01/20 a las 11:53
4

Todos los métodos para saber si la variable es NaN o None:

Ninguno tipo

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

Tipo de 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
4

Cómo eliminar elementos NaN (flotantes) de una lista de tipos de datos mixtos

Si tiene tipos mixtos en un iterable, aquí hay una solución que no usa 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]

La evaluación de cortocircuito significa que isnanno se llamará a valores que no sean del tipo 'float', ya que False and (…)se evalúa rápidamente Falsesin tener que evaluar el lado derecho.

3

En Python 3.6, la verificación de un valor de cadena x math.isnan (x) y np.isnan (x) genera un error. Entonces no puedo verificar si el valor dado es NaN o no si no sé de antemano que es un número. Lo siguiente parece resolver este problema

if str(x)=='nan' and type(x)!='str':
    print ('NaN')
else:
    print ('non NaN')
2

Comparación pd.isna, math.isnany np.isnany su flexibilidad tratar con diferentes tipos de objetos.

La siguiente tabla muestra si el tipo de objeto se puede verificar con el método dado:


+------------+-----+---------+------+--------+------+
|   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

El método más flexible para verificar diferentes tipos de valores perdidos.


Ninguna de las respuestas cubre la flexibilidad de pd.isna. Si bien math.isnany np.isnanvolverá Truea NaNlos valores, no se puede comprobar si hay diferentes tipos de objetos como Noneo cadenas. Ambos métodos devolverán un error, por lo que comprobar una lista con tipos mixtos será engorroso. Este while pd.isnaes flexible y devolverá el booleano correcto para diferentes tipos de tipos:

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])
1

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
-5

para cadenas en panda, tome pd.isnull:

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

la función como extracción de características para 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
2
  • ¿Qué hay de esta reducción? Max Kleiner 7/08/18 a las 13:36
  • isnull devuelve verdadero no solo para los valores NaN. Boris 20 abr.20 a las 13:51