Как я могу проверить значения NaN?

983

float('nan')результаты в Nan (не число). Но как я могу это проверить? Должно быть очень легко, но я не могу его найти.

Джек Ха
источник
20
Для некоторой истории NaN в Python, см. PEP 754. python.org/dev/peps/pep-0754
Крейг Маккуин

Ответы:

1284

math.isnan (х)

Возврат, 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, если хотите, этот ответ - просто предложение.
Гимел
2
@ SittingBull См. Docs.python.org/3/library/functions.html#float "Если аргумент является строкой, он должен содержать десятичное число" или "Infinity" "inf" "nan"
гимел
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 поддерживает Монику
360

Обычный способ проверить NaN - посмотреть, равен ли он самому себе:

def isNaN(num):
    return num != num
Крис Шут-Янг
источник
8
Слово предупреждения: процитируйте комментарий Медведя ниже: «Для людей, которые застряли на питоне <= 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или нет.

mavnn
источник
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 не был частью стандартной библиотеки. Сейчас я очень надеюсь, что это не так во многих местах!
мавн
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()решает мои проблемы. Спасибо!
Дартбхирава
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
x0s
источник
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 настолько чертовски большой, что удваивает размер любого скомпилированного приложения).

DaveTheScientist
источник
9
math.isfiniteне был представлен до Python 3.2, поэтому, учитывая, что ответ от @DaveTheScientist был опубликован в 2012 году, он не был «заново изобретать [колесо]» - решение по-прежнему
подходит
22

math.isnan ()

или сравните число с собой. NaN всегда! = NaN, в противном случае (например , если это число) сравнение должно преуспеть.

Томалак
источник
6
Для людей, увязших с питоном <= 2.5. Нэн! = Нэн не работал надежно. Используется вместо NumPy.
Медведь
16

Другой метод, если вы застряли на <2.6, у вас нет numpy, и у вас нет поддержки IEEE 754:

def isNaN(x):
    return str(x) == str(1e400*0)
Джош Ли
источник
12

Ну, я вошел в этот пост, потому что у меня были некоторые проблемы с функцией:

math.isnan()

Есть проблема при запуске этого кода:

a = "hello"
math.isnan(a)

Это вызывает исключение. Мое решение для этого состоит в том, чтобы сделать еще одну проверку:

def is_nan(x):
    return isinstance(x, float) and math.isnan(x)
IDOK
источник
3
Вероятно, это было отклонено, потому что isnan () принимает число с плавающей точкой, а не строку. В этой функции нет ничего плохого, и проблемы заключаются только в его попытке использовать ее. (Для этого конкретного варианта использования его решение является действительным, но это не ответ на этот вопрос.)
Питер Хансен
6
Будьте осторожны с проверкой типов таким способом. Это не будет работать, например, для numpy.float32 NaN. Лучше использовать попытку / кроме конструкции: def is_nan(x): try: return math.isnan(x) except: return False
Роб
3
NaN не означает, что значение не является допустимым числом. Это часть представления IEEE с плавающей запятой, указывающая, что конкретный результат не определен. например, 0 / 0. Поэтому спрашивать, является ли "привет" значением nan, бессмысленно.
Брайс М. Демпси
2
это лучше, потому что NaN может приземлиться в любом списке строк, целых чисел или чисел с плавающей запятой, поэтому полезная проверка
RAFIQ
Мне пришлось реализовать именно это для обработки строковых столбцов в пандах.
Кристиан Гарсия
7

С питоном <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, так что говорит твое предложение о valueсуществовании NaNили нет?
Махди
Что ж, будучи «не числом», все, что не может быть преобразовано в int, я полагаю, на самом деле не число, и оператор try не выполнится? Попробуйте вернуть true, кроме возврата false.
Чу
@chwi Ну, если понимать буквально «не число», вы правы, но здесь дело не в этом. На самом деле, я ищу именно то, что такое семантика NaN(как в Python, что вы могли бы получить float('inf') * 0), и, следовательно, хотя строка «Hello» не является числом, но это также не NaNпотому, что NaNпо-прежнему числовое значение!
Махди
@chwi: Вы правы, если обработка исключений предназначена для конкретного исключения. Но в этом ответе были обработаны общие исключения. Так что не нужно проверять int(value)За всеми исключениями, Falseбудет написано.
Харша Бияни
3

Все методы, чтобы определить, является ли переменная NaN или нет:

Ни один тип

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
siberiawolf61
источник
2

Как удалить NaN (float) элемент (ы) из списка смешанных типов данных

Если вы смешали типы в итерируемом, вот решение, которое не использует 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без необходимости оценивать правую часть.

sleblanc
источник
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)
Grzegorz
источник
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
J11
источник
-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.
Борис