Jak mogę sprawdzić wartości NaN?

979

float('nan')wyniki w Nan (nie liczba). Ale jak to sprawdzić? Powinno to być bardzo łatwe, ale nie mogę tego znaleźć.

Jack Ha
źródło
20
Aby zapoznać się z historią NaN w Pythonie, zobacz PEP 754. python.org/dev/peps/pep-0754
Craig McQueen

Odpowiedzi:

1275

math.isnan (x)

Zwraca, Truejeśli x jest NaN (nie liczbą) i w Falseprzeciwnym razie.

>>> import math
>>> x = float('nan')
>>> math.isnan(x)
True
gimel
źródło
5
@ charlie-parker: W Python3 math.isnan jest nadal częścią modułu matematycznego. docs.python.org/3/library/math.html#math.isnan . Jeśli chcesz, użyj numpy.isnan, ta odpowiedź to tylko sugestia.
gimel
2
@ SittingBull Patrz docs.python.org/3/library/functions.html#float "Jeśli argument jest łańcuchem, powinien zawierać liczbę dziesiętną" lub "Infinity" "inf" "nan"
gimel
35
jest math.isnanpreferowany np.isnan()?
TMWP
34
@ TMWP prawdopodobnie ... import numpyzajmuje około 15 MB pamięci RAM, podczas gdy import mathzajmuje około 0,2 MB
petrpulc
9
@TMWP: Jeśli używasz NumPy, numpy.isnanjest lepszym wyborem, ponieważ obsługuje tablice NumPy. Jeśli nie używasz NumPy, przyjmowanie zależności NumPy i poświęcanie czasu na ładowanie NumPy tylko na czek NaN nie jest korzystne (ale jeśli piszesz rodzaj kodu, który wykonuje kontrole NaN, prawdopodobnie powinieneś użyć NumPy).
user2357112 obsługuje Monikę
359

Zwykłym sposobem na sprawdzenie NaN jest sprawdzenie, czy jest on równy:

def isNaN(num):
    return num != num
Chris Jester-Young
źródło
8
Słowo ostrzeżenia: cytując komentarz Niedźwiedzia poniżej „Dla ludzi, którzy utknęli w python <= 2.5. Nan! = Nan nie działał niezawodnie. Zamiast tego użyłem numpy.” Powiedziawszy to, nigdy tak naprawdę nie widziałem, żeby zawiodła.
mavnn
22
Jestem pewien, że biorąc pod uwagę przeciążenie operatora, istnieje wiele sposobów na pomylenie tej funkcji. idź z math.isnan ()
djsadinoff,
4
W powyższej specyfikacji 754 jest powiedziane, że NaN == NaN zawsze powinien być fałszywy, chociaż nie zawsze jest zaimplementowany jako taki. Czy nie jest możliwe, w ten sposób matematyka i / lub numpy sprawdza to pod maską?
Hari Ganesan
Dzięki . jest to również 15-20 razy szybsze niż użycie np.isnan, jeśli wykonujesz operację na skalar
thomas.mac
5
Mimo, że to działa i do pewnego stopnia ma sens, jestem człowiekiem z zasadami i niniejszym oświadczam, że jest to zabronione czary. Zamiast tego użyj math.isnan.
Gonzalo
152

numpy.isnan(number)powie ci, czy to jest NaNczy nie.

mavnn
źródło
3
Działa również w Pythonie w wersji 2.7.
Michel Keijzers,
6
numpy.all(numpy.isnan(data_list))przydaje się również, gdy trzeba ustalić, czy wszystkie elementy na liście są nan
Jay P.
3
Nie ma potrzeby korzystania z NumPy:all(map(math.isnan, [float("nan")]*5))
sleblanc
6
Kiedy ta odpowiedź została napisana 6 lat temu, Python 2.5 był nadal w powszechnym użyciu - a math.isnan nie był częścią standardowej biblioteki. Teraz mam nadzieję, że w wielu miejscach tak nie jest!
mavnn
4
zwróć uwagę, że np.isnan () nie obsługuje decimal.Decimal typu (tylu funkcji numpy). math.isnan () obsługuje.
kometa
55

Oto trzy sposoby testowania zmiennej na „NaN” lub nie.

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

Wynik

It's pd.isna  : True
It's np.isnan  : True
It's math.isnan  : True
M. Hamza Rajput
źródło
2
pd.isna (wartość) zaoszczędził wiele problemów! działa jak urok!
abhishake
1
ps.isna()rozwiązuje moje problemy. Dzięki!
darthbhyrava
32

oto odpowiedź współpracująca z:

  • Implementacje NaN zgodne ze standardem IEEE 754
    • tj .: NaN: python float('nan'), numpy.nan...
  • wszelkie inne obiekty: ciąg znaków lub cokolwiek innego (nie stwarza wyjątków, jeśli zostaną napotkane)

NaN zaimplementowany zgodnie ze standardem jest jedyną wartością, dla której porównanie nierówności z samym sobą powinno zwrócić True:

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

I kilka przykładów:

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

Wynik:

nan      : True
nan      : True
55       : False
'string' : False
<function <lambda> at 0x000000000927BF28> : False
x0s
źródło
1
Seria, którą sprawdzam, to ciągi z brakującymi wartościami to „nans” (???), więc to rozwiązanie działa tam, gdzie inne zawiodły.
keithpjolley,
numpy.nanjest zwykłym floatobiektem Pythona , podobnie jak ten zwracany przez float('nan'). Większość NaN, które spotkasz w NumPy, nie będzie numpy.nanobiektem.
user2357112 obsługuje Monikę
numpy.nanokreśla jej wartość NaN na własną rękę w podstawowej biblioteki w C . Nie zawija NaN Pythona. Ale teraz oba są zgodne ze standardem IEEE 754, ponieważ polegają na API C99.
x0s
@ user2357112supportsMonica: Python i numpy NaN faktycznie nie zachowują się w ten sam sposób: float('nan') is float('nan')(nie-unikalny) i np.nan is np.nan(unikalny)
x0s
@ x0s: To nie ma nic wspólnego z NumPy. np.nanjest konkretnym obiektem, a każde float('nan')wywołanie tworzy nowy obiekt. Gdybyś to zrobił nan = float('nan'), ty też byś to dostał nan is nan. Jeśli skonstruował rzeczywistą NumPy NaN z czymś takim np.float64('nan'), to można dostać np.float64('nan') is not np.float64('nan')zbyt .
user2357112 obsługuje Monikę
28

Właściwie to po prostu na to wpadłem, ale dla mnie sprawdzało to nan, inf lub inf. Właśnie użyłem

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

Dotyczy to liczb, fałszu dla nan i obu inf, i spowoduje wyjątek dla takich rzeczy jak ciągi znaków lub inne typy (co jest prawdopodobnie dobrą rzeczą). Nie wymaga to również importowania bibliotek takich jak matematyka czy numpy (numpy jest tak cholernie duże, że podwaja rozmiar każdej skompilowanej aplikacji).

DaveTheScientist
źródło
9
math.isfinitezostał wprowadzony dopiero w Pythonie 3.2, więc biorąc pod uwagę odpowiedź @DaveTheScientist opublikowano w 2012 roku, nie było to dokładnie „wynaleźć koło” - rozwiązanie nadal dotyczy osób pracujących z Pythonem 2.
sudo_coffee
22

math.isnan ()

lub porównaj liczbę z samym sobą. NaN jest zawsze! = NaN, w przeciwnym razie (np. Jeśli jest to liczba) porównanie powinno się powieść.

Tomalak
źródło
6
Dla osób, które utknęły z pythonem <= 2,5. Nan! = Nan nie działał niezawodnie. Zamiast tego użyto numpy.
Niedźwiedź
16

Inna metoda, jeśli utkniesz na <2.6, nie masz numpy i nie masz obsługi IEEE 754:

def isNaN(x):
    return str(x) == str(1e400*0)
Josh Lee
źródło
11

Wpisałem ten post, ponieważ miałem pewne problemy z funkcją:

math.isnan()

Występuje problem po uruchomieniu tego kodu:

a = "hello"
math.isnan(a)

Rodzi wyjątek. Moim rozwiązaniem jest ponowne sprawdzenie:

def is_nan(x):
    return isinstance(x, float) and math.isnan(x)
Idok
źródło
3
Prawdopodobnie zostało to zanegowane, ponieważ isnan () przyjmuje liczbę zmiennoprzecinkową, a nie ciąg znaków. Nie ma nic złego w tej funkcji, a problemy dotyczą tylko jego próby użycia. (W tym konkretnym przypadku użycia jego rozwiązanie jest poprawne, ale nie jest to odpowiedź na to pytanie.)
Peter Hansen
6
Ostrożnie sprawdzaj typy w ten sposób. To nie zadziała np. Dla numpy.float32 NaN. Lepiej użyć konstrukcji try / try: def is_nan(x): try: return math.isnan(x) except: return False
Rob
3
NaN nie oznacza, że ​​wartość nie jest poprawną liczbą. Częścią reprezentacji zmiennoprzecinkowej IEEE jest określenie, że określony wynik jest niezdefiniowany. np. 0 / 0. Dlatego pytanie, czy „cześć” jest nan, jest bez znaczenia.
Brice M. Dempsey,
2
jest to lepsze, ponieważ NaN może wylądować na dowolnej liście ciągów, liczb całkowitych lub liczb
zmiennoprzecinkowych
8

Z pythonem <2.6 skończyłem z

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

Działa to dla mnie z Pythonem 2.5.1 na pudełku Solaris 5.9 iz Pythonem 2.6.5 na Ubuntu 10

Mauro Bianchi
źródło
6
Nie jest to zbyt przenośne, jak to czasem nazywa Windows-1.#IND
Mike T
5

Otrzymuję dane z usługi internetowej, która wysyła NaNjako ciąg znaków 'Nan'. Ale w moich danych mogą znajdować się również inne rodzaje ciągów, więc prosty float(value)może zgłosić wyjątek. Użyłem następującego wariantu zaakceptowanej odpowiedzi:

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

Wymaganie:

isnan('hello') == False
isnan('NaN') == True
isnan(100) == False
isnan(float('nan')) = True
Mahdi
źródło
1
lubtry: int(value)
chwi
@chwi, więc co twoja sugestia mówi o valuebyciu NaNczy nie?
Mahdi
Cóż, będąc „nie liczbą”, cokolwiek, co nie może być przypisane do liczby int, myślę, że w rzeczywistości nie jest liczbą, a instrukcja try zawiedzie? Spróbuj zwrócić true, z wyjątkiem return false.
chwi
@chwi Cóż, biorąc dosłownie „nie liczbę”, masz rację, ale nie o to tutaj chodzi. W rzeczywistości szukam dokładnie tego, co to jest semantyka NaN(jak w pythonie, co można uzyskać float('inf') * 0), a zatem chociaż ciąg „Hello” nie jest liczbą, ale nie jest tak, NaNponieważ NaNwciąż jest wartością liczbową!
Mahdi
@chwi: Masz rację, jeśli obsługa wyjątków dotyczy konkretnego wyjątku. Ale w tej odpowiedzi obsłużono wyjątek ogólny. Więc nie trzeba sprawdzać int(value)Dla wszystkich wyjątków Falsezostaną zapisane.
Harsha Biyani
3

Wszystkie metody określania, czy zmienna ma wartość NaN czy None:

Brak typu

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

Typ 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
źródło
2

Jak usunąć elementy NaN (float) z listy mieszanych typów danych

Jeśli masz iterowalne typy mieszane, oto rozwiązanie, które nie używa 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]

Ocena zwarcia oznacza, że isnannie będą wywoływane wartości, które nie są typu „zmiennoprzecinkowego”, jak False and (…)szybko ocenia, Falsebez konieczności oceny prawej strony.

sleblanc
źródło
1

W Pythonie 3.6 sprawdzenie wartości ciągu x math.isnan (x) i np.isnan (x) powoduje błąd. Nie mogę więc sprawdzić, czy podana wartość to NaN, czy nie, jeśli wcześniej nie wiem, że jest to liczba. Poniższe wydają się rozwiązać ten problem

if str(x)=='nan' and type(x)!='str':
    print ('NaN')
else:
    print ('non NaN')
Valentin Goikhman
źródło
1

Wygląda na to, że sprawdzenie, czy jest równe sobie

x!=x

jest najszybszy.

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
źródło
0

Dla pływaka typu nan

>>> 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
źródło
-5

dla ciągów w pandzie weź pd.isnull:

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

funkcja jako ekstrakcja funkcji dla 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
źródło
Po co ta obniżka?
Max Kleiner
isnull zwraca true dla nie tylko wartości NaN.
Boris