Як я можу перевірити значення 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.