Як я можу перевірити значення NaN?


979

float('nan')результати в Нан (не число). Але як мені це перевірити? Це повинно бути дуже легко, але я не можу його знайти.


20
Докладніше про NaN в Python див. PEP 754. python.org/dev/peps/pep-0754
Craig McQueen

Відповіді:


1275

math.isnan (x)

Повертається, Trueякщо x - NaN (не число) та Falseінше.

>>> import math
>>> x = float('nan')
>>> math.isnan(x)
True

5
@ charlie-parker: У Python3 math.isnan досі є частиною математичного модуля. docs.python.org/3/library/math.html#math.isnan . Якщо бажаєте, використовуйте numpy.isnan, ця відповідь - лише пропозиція.
gimel

2
@ SittingBull Дивіться docs.python.org/3/library/functions.html#float "Якщо аргумент є рядком, він повинен містити десяткове число", або "Infinity" "inf" "nan"
gimel

35
є math.isnanкращим , щоб np.isnan()?
TMWP

34
@TMWP можливо ... import numpyзаймає близько 15 Мб оперативної пам’яті, тоді як import mathзаймає близько 0,2 Мб
petrpulc

9
@TMWP: Якщо ви використовуєте NumPy, numpy.isnanце чудовий вибір, оскільки він обробляє масиви NumPy. Якщо ви не використовуєте NumPy, немає користі брати залежність від NumPy і витрачати час на завантаження NumPy лише для перевірки NaN (але якщо ви пишете тип коду, який робить перевірку NaN, швидше за все, ви повинні використовувати NumPy).
user2357112 підтримує Моніку

359

Звичайний спосіб перевірити наявність NaN - це перевірити, чи рівний він самому собі:

def isNaN(num):
    return num != num

8
Слово попередження: цитуючи коментар Ведмедя нижче "Для людей, застряглих у python <= 2,5. Nan! = Nan не працював надійно. Натомість використовували numpy". Сказавши це, я насправді ніколи не бачив, щоб він провалився.
mavnn

22
Я впевнений, що, зважаючи на перевантаження оператора, існує багато способів переплутати цю функцію. ідіть з math.isnan ()
djsadinoff

4
У зазначеній вище специфікації 754 сказано, що NaN == NaN завжди повинен бути помилковим, хоча він не завжди реалізується як такий. Чи не можливо це так, як математика та / або нуме перевірити це під кришкою?
Харі Ганесан

Дякую . це також у 15-20 разів швидше, ніж використання np.isnan, якщо ви робите операцію на скалярі
thomas.mac

5
Хоча це працює і, до певної міри, має сенс, я людина з принципами і цим заявляю це як заборонене чаклунство. Будь ласка, використовуйте math.isnan замість цього.
Гонсало

152

numpy.isnan(number)повідомляє вам, NaNчи ні.


3
Також працює у версії python 2.7.
Мішель Кейзерс

6
numpy.all(numpy.isnan(data_list))також корисно, якщо вам потрібно визначити, чи всі елементи у списку нан
Jay P.

3
Не потрібно NumPy:all(map(math.isnan, [float("nan")]*5))
sleblanc

6
Коли цю відповідь було написано 6 років тому, Python 2.5 все ще використовувався - і math.isnan не входив до стандартної бібліотеки. Зараз я дуже сподіваюся, що це не так у багатьох місцях!
mavnn

4
зауважте, що np.isnan () не обробляє десятковий тип. Десятковий тип (стільки ж функції numpy). math.isnan () справді справляється.
конт

55

Ось три способи тестування змінної "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)}")

Вихідні дані

It's pd.isna  : True
It's np.isnan  : True
It's math.isnan  : True

2
pd.isna (значення) врятував багато неприємностей! працює як шарм!
abhishake

1
ps.isna()вирішує мої питання. Дякую!
darthbhyrava

32

ось відповідь, що працює з:

  • Реалізація NaN, що відповідає стандарту IEEE 754
    • тобто: пітона NaN: float('nan'), numpy.nan...
  • будь-які інші об'єкти: рядок або будь-який інший (не створює винятків, якщо вони виникають)

NaN, реалізований за стандартом, є єдиним значенням, для якого порівняння нерівності з самим собою повинно повернути True:

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

І кілька прикладів:

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

Вихід:

nan      : True
nan      : True
55       : False
'string' : False
<function <lambda> at 0x000000000927BF28> : False

1
Серія, яку я перевіряю, - це рядки з пропущеними значеннями "nans" (???), тому це рішення працює там, де інші не вдається.
keithpjolley

numpy.nanє звичайним floatоб’єктом Python , як і вид, який повертається float('nan'). Більшість NaN, з якими ви стикаєтесь у NumPy, не будуть numpy.nanоб'єктом.
user2357112 підтримує Моніку

numpy.nanвизначає його значення NaN по собі в базовій бібліотеці C . Він не загортає NaN пітона. Але тепер вони обидва відповідають стандарту IEEE 754, оскільки вони покладаються на C99 API.
x0s

@ user2357112supportsMonica: Python та numpy NaN насправді ведуть себе не однаково: float('nan') is float('nan')(неповторно) та np.nan is np.nan(унікально)
x0s

@ x0s: Це не має нічого спільного з NumPy. np.nanє конкретним об'єктом, тоді як кожен float('nan')виклик створює новий об'єкт. Якби ти це зробив nan = float('nan'), то ти теж отримав би nan is nan. Якщо ви побудували фактичний NumPy NaN що - щось на зразок np.float64('nan'), то ви отримаєте np.float64('nan') is not np.float64('nan')занадто .
user2357112 підтримує Моніку

28

Я насправді просто натрапив на це, але для мене це перевірка на nan, -inf чи inf. Я просто використовував

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

Це справедливо для чисел, false для nan і обох inf, і створить виняток для таких речей, як рядки або інші типи (що, мабуть, добре). Крім того, для цього не потрібно імпортувати будь-які бібліотеки, такі як математика або numpy (numpy настільки чортово великий, що подвоює розмір будь-якої складеної програми).


9
math.isfiniteне був представлений до Python 3.2, тому, зважаючи на відповідь @DaveTheScientist, було розміщено в 2012 році, це було не точно "винаходити колесо" - рішення все ще стосується тих, хто працює з Python 2.
sudo_coffee

22

math.isnan ()

або порівняти число до себе. NaN завжди! = NaN, інакше (наприклад, якщо це так) це число) порівняння має досягти успіху.


6
Для людей, що застрягли з пітоном <= 2,5. Нан! = Нан не працював надійно. Замість цього використовується numpy.
Ведмідь

16

Ще один метод, якщо ви застрягли на <2.6, у вас немає нумеру і у вас немає підтримки IEEE 754:

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

11

Добре я зайшов у цю посаду, тому що у мене виникли деякі проблеми з функцією:

math.isnan()

Під час запуску цього коду є проблеми:

a = "hello"
math.isnan(a)

Це породжує виняток. Моє рішення для цього - зробити ще одну перевірку:

def is_nan(x):
    return isinstance(x, float) and math.isnan(x)

3
Ймовірно, це було спровоковано, тому що isnan () приймає поплавок, а не струну. З функцією немає нічого поганого, і проблеми полягають лише в спробі його використання. (Для цього конкретного випадку використання його рішення є дійсним, але це не відповідь на це питання.)
Пітер Хансен

6
Будьте уважні до перевірки типів таким чином. Це не буде працювати, наприклад, для numpy.float32 NaN. Краще скористатися спробу / крім будівництва: def is_nan(x): try: return math.isnan(x) except: return False
Роб,

3
NaN не означає, що значення не є дійсним числом. Це частина представлення IEEE з плаваючою точкою, щоб вказати, що конкретний результат не визначений. наприклад, 0 / 0. Тому запитувати, чи "привіт", нан - це безглуздо.
Бріс М. Демпсі

2
це краще, тому що NaN може висаджуватися в будь-який список струн, ints або
floats

8

З python <2.6 я закінчив

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

Це працює для мене з python 2.5.1 на вікні Solaris 5.9 та з python 2.6.5 на Ubuntu 10


6
Це не надто портативно, як Windows іноді називає це-1.#IND
Mike T

5

Я отримую дані від веб-сервісу, який надсилає NaNяк рядок 'Nan'. Але в моїх даних можуть бути й інші види рядків, тому простий float(value)може викинути виняток. Я використав наступний варіант прийнятої відповіді:

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

Вимога:

isnan('hello') == False
isnan('NaN') == True
isnan(100) == False
isnan(float('nan')) = True

1
абоtry: int(value)
chwi

@chwi, так що ваша пропозиція говорить про valueте, NaNчи ні?
Махді

Що ж, будучи "не числом", що-небудь, що не можна закинути на int, я думаю, насправді це не число, і оператор спробу не вдасться? Спробуйте повернути справжнє, крім повернення хибного.
chwi

@chwi Ну, прийнявши буквально "не число", ти маєш рацію, але тут справа не в цьому. Насправді я шукаю саме те, що таке семантика NaN(як, наприклад, у python, що ви могли б отримати float('inf') * 0), і, хоча рядок "Hello" - це не число, але це також не NaNтому NaN, що все ще є числовим значенням!
Махді

@chwi: Ви маєте рацію, якщо обробка винятків призначена для конкретного виключення. Але у цій відповіді розроблено загальний виняток. Тому не потрібно перевіряти. int(value)За всіх винятків Falseбуде написано.
Харша Біяні

3

Усі методи визначити, чи є змінна NaN чи None:

Немає типу

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

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

2

Як видалити елементи NaN (плаваючі) зі списку змішаних типів даних

Якщо ви маєте змішані типи в ітерабелі, ось рішення, яке не використовує 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]

Оцінка короткого замикання означає, що isnanне буде викликано значення, що не мають типу "float", як False and (…)швидко оцінюється до Falseбез необхідності оцінювати праву частину.


1

У Python 3.6 перевірка значень рядка x math.isnan (x) та np.isnan (x) викликає помилку. Тому я не можу перевірити, чи задане значення NaN чи ні, якщо я заздалегідь не знаю, це число. Наступне, здається, вирішує це питання

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

1

Здається, перевірити, чи рівна вона сама собі

x!=x

найшвидший.

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)

0

Для нан типу 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

для рядків у панді прийняти pd.isnull:

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

функція як вилучення функції для 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

Що за це зменшення?
Макс Клейнер

isnull повертає true для не лише значень NaN.
Борис
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.