Como posso verificar os valores de NaN?

981

float('nan')resulta em Nan (não é um número). Mas como faço para verificar isso? Deve ser muito fácil, mas não consigo encontrá-lo.

Jack Ha
fonte
20
Para alguma história do NaN em Python, consulte PEP 754. python.org/dev/peps/pep-0754
Craig McQueen

Respostas:

1282

math.isnan (x)

Retorne Truese x for um NaN (não um número) e Falsecaso contrário.

>>> import math
>>> x = float('nan')
>>> math.isnan(x)
True
gimel
fonte
5
@ charlie-parker: No Python3, math.isnan ainda faz parte do módulo de matemática. docs.python.org/3/library/math.html#math.isnan . Use numpy.isnan, se desejar, esta resposta é apenas uma sugestão.
guimel
2
@ SittingBull Consulte docs.python.org/3/library/functions.html#float "Se o argumento for uma string, ele deverá conter um número decimal" ou "Infinito" "inf" "nan"
gimel
35
é math.isnanpreferido para np.isnan()?
TMWP 01/08/19
34
@TMWP possivelmente ... import numpyleva cerca de 15 MB de RAM, enquanto que import mathleva algum 0,2 MB
petrpulc
9
@TMWP: Se você estiver usando o NumPy, numpy.isnané uma escolha superior, pois lida com matrizes NumPy. Se você não estiver usando NumPy, não há nenhum benefício para tomar uma dependência NumPy e passar o tempo para carregar NumPy apenas para uma verificação de NaN (mas se você está escrevendo o tipo de código que faz verificações Nan, é provável que você deve estar usando NumPy).
user2357112 suporta Monica
359

A maneira usual de testar um NaN é ver se é igual a si mesmo:

def isNaN(num):
    return num != num
Chris Jester-Young
fonte
8
Palavra de aviso: citando o comentário de Bear abaixo "Para pessoas presas com python <= 2.5. Nan! = Nan não funcionou de maneira confiável. Usou numpy em vez disso." Dito isto, eu realmente nunca vi isso falhar.
mavnn
22
Tenho certeza de que, dada a sobrecarga do operador, há muitas maneiras de confundir essa função. Vá com math.isnan ()
djsadinoff
4
Diz nas 754 especificações mencionadas acima que NaN == NaN deve sempre ser falso, embora nem sempre seja implementado como tal. Não é possível, é assim que a matemática e / ou o numpy controlam isso de alguma maneira?
Hari Ganesan
Obrigado . este é também 15-20x vezes mais rápido do que usar np.isnan se fazer a operação em um escalar
thomas.mac
5
Embora isso funcione e, até certo ponto, faça sentido, sou humano com princípios e declaro isso como bruxaria proibida. Por favor, use math.isnan.
Gonzalo
152

numpy.isnan(number)diz se é NaNou não.

mavnn
fonte
3
Também funciona na versão 2.7 do python.
Michel Keijzers
6
numpy.all(numpy.isnan(data_list))também é útil se você precisar determinar se todos os elementos da lista são nan
Jay P.
3
Não há necessidade de NumPy:all(map(math.isnan, [float("nan")]*5))
sleblanc 28/03
6
Quando essa resposta foi escrita há 6 anos, o Python 2.5 ainda era de uso comum - e math.isnan não fazia parte da biblioteca padrão. Agora, dias realmente espero que esse não seja o caso em muitos lugares!
mavnn
4
Observe que o np.isnan () não manipula o tipo decimal.Decimal (como a função de muitos numpy). math.isnan () manipula.
comte
55

Aqui estão três maneiras pelas quais você pode testar uma variável: "NaN" ou não.

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

Resultado

It's pd.isna  : True
It's np.isnan  : True
It's math.isnan  : True
M. Hamza Rajput
fonte
2
O pd.isna (valor) salvou muitos problemas! trabalhando como um encanto!
abhishake
1
ps.isna()resolve meus problemas. Obrigado!
darthbhyrava 18/03
32

aqui está uma resposta trabalhando com:

  • Implementações de NaN respeitando o padrão IEEE 754
    • ou seja: de python NaN: float('nan'), numpy.nan...
  • quaisquer outros objetos: string ou qualquer outra coisa (não gera exceções, se encontrado)

Um NaN implementado seguindo o padrão é o único valor para o qual a comparação de desigualdade com ele mesmo deve retornar True:

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

E alguns exemplos:

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

Resultado:

nan      : True
nan      : True
55       : False
'string' : False
<function <lambda> at 0x000000000927BF28> : False
x0s
fonte
1
A série que estou verificando é que as strings com valores ausentes são 'nans' (???), portanto esta solução funciona onde outras falharam.
Keithpjolley #
numpy.nané um floatobjeto Python comum , assim como o tipo retornado por float('nan'). A maioria dos NaNs encontrados no NumPy não será o numpy.nanobjeto.
user2357112 suporta Monica 14/04
numpy.nandefine seu valor NaN por conta própria na biblioteca subjacente em C . Não envolve o NaN do python. Mas agora, ambos estão em conformidade com o padrão IEEE 754, pois contam com a API C99.
x0s 22/04
@ user2357112supportsMonica: Python e numpy NaN na verdade não se comportam da mesma maneira: float('nan') is float('nan')(não-únicos) e np.nan is np.nan(únicos)
x0s
@ x0s: Isso não tem nada a ver com o NumPy. np.nané um objeto específico, enquanto cada float('nan')chamada produz um novo objeto. Se você fizesse nan = float('nan'), nan is nantambém conseguiria . Se você construísse um NumPy NaN real com algo parecido np.float64('nan'), também conseguirianp.float64('nan') is not np.float64('nan') .
user2357112 suporta Monica
28

Na verdade, eu me deparei com isso, mas para mim estava checando nan, -inf ou inf. Eu apenas usei

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

Isso é verdadeiro para números, falso para nan e ambos inf, e gerará uma exceção para coisas como strings ou outros tipos (o que provavelmente é uma coisa boa). Além disso, isso não requer a importação de bibliotecas como matemática ou numpy (numpy é tão grande que dobra o tamanho de qualquer aplicativo compilado).

DaveTheScientist
fonte
9
math.isfinitenão foi introduzido até o Python 3.2, então, dada a resposta do @DaveTheScientist, foi postada em 2012, não era exatamente "reinventar a roda" - a solução ainda é válida para aqueles que trabalham com o Python 2. #
sudo_coffee
22

math.isnan ()

ou compare o número consigo mesmo. NaN é sempre! = NaN, caso contrário (por exemplo, se for um número), a comparação deve ser bem-sucedida.

Tomalak
fonte
6
Para pessoas presas com python <= 2.5. Nan! = Nan não funcionou de forma confiável. Usado numpy em vez disso.
Bear
16

Outro método, se você estiver preso em <2.6, não ficará entorpecido e não terá suporte ao IEEE 754:

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

Bem, eu entrei neste post, porque tive alguns problemas com a função:

math.isnan()

Há um problema ao executar este código:

a = "hello"
math.isnan(a)

Isso gera exceção. Minha solução para isso é fazer outra verificação:

def is_nan(x):
    return isinstance(x, float) and math.isnan(x)
Idok
fonte
3
Provavelmente foi diminuído porque isnan () pega um float, não uma string. Não há nada de errado com a função, e os problemas estão apenas na tentativa de usá-la. (Para esse caso de uso particular, a sua solução é válido, mas não é uma resposta a esta pergunta.)
Peter Hansen
6
Cuidado ao verificar os tipos dessa maneira. Isso não funcionará, por exemplo, para NaNs numpy.float32. Melhor usar uma tentativa / exceto construção: def is_nan(x): try: return math.isnan(x) except: return False
Rob
3
NaN não significa que um valor não é um número válido. Faz parte da representação de ponto flutuante IEEE especificar que um resultado específico é indefinido. por exemplo, 0 / 0. Portanto, perguntar se "olá" é nan não tem sentido.
Brice M. Dempsey
2
este é melhor porque NaN pode pousar em qualquer lista de strings, ints ou floats, cheque tão útil
RAFIQ
Eu tive que implementar exatamente isso para lidar com colunas de string em pandas.
Cristian Garcia
7

Com python <2.6 acabei com

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

Isso funciona para mim com python 2.5.1 em uma caixa Solaris 5.9 e com python 2.6.5 no Ubuntu 10

Mauro Bianchi
fonte
6
Isto não é muito portátil, como o Windows, por vezes, chama isso-1.#IND
Mike T
5

Estou recebendo os dados de um serviço da web que envia NaNcomo uma string 'Nan'. Mas também poderia haver outros tipos de string nos meus dados, portanto, um simples float(value)poderia gerar uma exceção. Eu usei a seguinte variante da resposta aceita:

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

Requerimento:

isnan('hello') == False
isnan('NaN') == True
isnan(100) == False
isnan(float('nan')) = True
Mahdi
fonte
1
outry: int(value)
chwi
@chwi Então, o que sua sugestão diz sobre valueser NaNou não?
Mahdi
Bem, sendo "não um número", qualquer coisa que não possa ser convertida para um int, acho que na verdade não é um número, e a instrução try falhará? Tente, retorne verdadeiro, exceto retorne falso.
7116 chwi
@chwi Bem, considerando "não um número" literalmente, você está certo, mas esse não é o ponto aqui. Na verdade, estou procurando exatamente qual é a semântica NaN(como em python, o que você poderia obter float('inf') * 0) e, portanto, embora a string 'Hello' não seja um número, mas também não é NaNporque NaNainda é um valor numérico!
Mahdi
@chwi: Você está correto, se o tratamento de exceções é para uma exceção específica. Mas nesta resposta, exceções genéricas foram tratadas. Portanto, não há necessidade de verificar int(value)Por todas as exceções, Falseserá gravado.
Harsha Biyani 15/01
3

Todos os métodos para saber se a variável é NaN ou None:

Nenhum 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 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
fonte
2

Como remover itens NaN (flutuantes) de uma lista de tipos de dados mistos

Se você misturou tipos em um iterável, aqui está uma solução que não 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]

A avaliação de curto-circuito significa que isnannão serão chamados valores que não são do tipo 'flutuante', como é False and (…)avaliado rapidamente, Falsesem a necessidade de avaliar o lado direito.

sleblanc
fonte
1

No Python 3.6, a verificação de um valor de string x math.isnan (x) e np.isnan (x) gera um erro. Portanto, não posso verificar se o valor fornecido é NaN ou não, se não souber de antemão que é um número. O seguinte parece resolver este problema

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

Parece que verificar se é igual a si mesmo

x!=x

é o mais 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)
Grzegorz
fonte
0

Para nan do tipo 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
J11
fonte
-5

para seqüências de caracteres no panda, pegue pd.isnull:

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

a função como extração de recurso 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
Max Kleiner
fonte
O que para essa redução?
Max Kleiner
isnull retorna true, não apenas para os valores de NaN.
Boris