ฉันจะตรวจสอบค่า NaN ได้อย่างไร


981

float('nan')ผลลัพธ์ในน่าน (ไม่ใช่ตัวเลข) แต่ฉันจะตรวจสอบได้อย่างไร น่าจะง่ายมาก แต่ฉันหามันไม่เจอ


20
สำหรับประวัติของ NaN ใน Python ดูที่ PEP 754 python.org/dev/peps/pep-0754
Craig McQueen

คำตอบ:


1278

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ใช้เวลาประมาณ RAM 15 MB ในขณะที่import mathใช้เวลา 0,2 MB บางส่วน
petrpulc

9
@TMWP: หากคุณกำลังใช้ NumPy numpy.isnanเป็นตัวเลือกที่ดีกว่าเพราะจัดการกับ NumPy arrays หากคุณไม่ได้ใช้ NumPy ไม่มีประโยชน์ที่จะได้รับการพึ่งพา NumPy และใช้เวลาในการโหลด NumPy เพียงเพื่อตรวจสอบ NaN (แต่ถ้าคุณกำลังเขียนโค้ดประเภทที่ทำหน้าที่ตรวจสอบ NaN เป็นไปได้ว่าคุณควรจะใช้ NumPy)
user2357112 รองรับ Monica

359

วิธีปกติในการทดสอบ NaN คือดูว่ามีค่าเท่ากันหรือไม่:

def isNaN(num):
    return num != num

8
คำเตือน: การอ้างอิงความคิดเห็นของ Bear ด้านล่าง "สำหรับผู้ที่ติดกับ python <= 2.5. Nan! = น่านไม่สามารถทำงานได้อย่างน่าเชื่อถือใช้ numpy แทน" ต้องบอกว่าฉันไม่เคยเห็นมันล้มเหลว
mavnn

22
ฉันแน่ใจว่าจากการที่ผู้ประกอบการบรรทุกเกินพิกัดมีหลายวิธีที่ฉันสามารถทำให้ฟังก์ชั่นนี้สับสนได้ go with math.isnan ()
djsadinoff

4
มันบอกว่าในสเป็ค 754 ที่กล่าวถึงข้างต้นว่า NaN == NaN ควรเป็นเท็จเสมอแม้ว่ามันจะไม่ถูกนำไปใช้เช่นนี้เสมอไป เป็นไปไม่ได้หรือว่านี่เป็นวิธีการทางคณิตศาสตร์และ / หรือการตรวจสอบที่ไม่ดีภายใต้ประทุน
Hari Ganesan

ขอบคุณ นี่ยังเร็วกว่า 15-20 เท่าเมื่อใช้ np.isnan ถ้าใช้งานกับ scalar
thomas.mac

5
แม้ว่างานนี้และในระดับที่เหมาะสมฉันเป็นมนุษย์ที่มีหลักการและฉันขอประกาศว่านี่เป็นคาถาต้องห้าม โปรดใช้ math.isnan แทน
กอนซาโล่

152

numpy.isnan(number)บอกคุณว่ามันเป็นNaNหรือไม่


3
ทำงานในหลามเวอร์ชั่น 2.7 ด้วย
Michel Keijzers

6
numpy.all(numpy.isnan(data_list))นอกจากนี้ยังมีประโยชน์หากคุณต้องการตรวจสอบว่าองค์ประกอบทั้งหมดในรายการเป็นน่าน
เจย์พี

3
ไม่จำเป็นสำหรับ NumPy:all(map(math.isnan, [float("nan")]*5))
sleblanc

6
เมื่อคำตอบนี้ถูกเขียนขึ้นเมื่อ 6 ปีที่แล้ว Python 2.5 ยังใช้งานทั่วไป - และ math.isnan ไม่ได้เป็นส่วนหนึ่งของไลบรารีมาตรฐาน วันนี้ฉันหวังว่าจะไม่เป็นอย่างนั้นในหลาย ๆ ที่!
mavnn

4
โปรดทราบว่า np.isnan () ไม่จัดการทศนิยมประเภททศนิยม (ฟังก์ชั่นจำนวนมากของ numpy) math.isnan () จัดการ
comte

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
    • เช่น: หลามน่านfloat('nan'), numpy.nan...
  • วัตถุอื่นใด: สตริงหรืออะไรก็ตาม (ไม่ยกข้อยกเว้นหากพบ)

NaN ดำเนินการตามมาตรฐานเป็นเพียงค่าเดียวที่การเปรียบเทียบความไม่เท่าเทียมกับตัวมันเองควรคืนค่าเป็นจริง:

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 float('nan')NaN ส่วนใหญ่ที่คุณพบใน NumPy จะไม่ใช่numpy.nanวัตถุ
user2357112 รองรับ Monica

numpy.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 น่านกับสิ่งที่ต้องการnp.float64('nan')แล้วคุณจะได้รับnp.float64('nan') is not np.float64('nan')มากเกินไป
user2357112 รองรับ Monica

28

ที่จริงฉันเพิ่งพบเจอปัญหานี้ แต่สำหรับฉันมันคือการตรวจสอบว่าน่าน -inf หรือ inf ฉันเพิ่งใช้

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

นี่เป็นเรื่องจริงสำหรับตัวเลขเท็จสำหรับน่านและทั้ง inf และจะเพิ่มข้อยกเว้นสำหรับสิ่งต่าง ๆ เช่นสตริงหรือประเภทอื่น ๆ (ซึ่งอาจเป็นสิ่งที่ดี) นอกจากนี้สิ่งนี้ไม่จำเป็นต้องนำเข้าไลบรารีใด ๆ เช่น math หรือ numpy (numpy นั้นใหญ่มากจนขนาดของแอปพลิเคชั่นที่คอมไพล์แล้ว)


9
math.isfiniteไม่ได้ถูกนำมาใช้จนกระทั่ง Python 3.2 ดังนั้นคำตอบจาก @DaveTheScientist จึงถูกโพสต์ในปี 2012 มันไม่ใช่ "reinvent [ing] the wheel" - โซลูชันยังคงใช้ได้สำหรับผู้ที่ทำงานกับ Python 2
sudo_coffee

22

math.isnan ()

หรือเปรียบเทียบตัวเลขกับตัวเอง NaN อยู่เสมอ! = NaN มิฉะนั้น (เช่นถ้าเป็นตัวเลข) การเปรียบเทียบควรสำเร็จ


6
สำหรับคนที่ติด python <= 2.5 น่าน! = น่านไม่สามารถทำงานได้อย่างน่าเชื่อถือ ใช้จำนวนมากแทน
Bear

16

อีกวิธีหนึ่งหากคุณติดค้างที่ <2.6 คุณไม่มีปัญหาและคุณไม่มีการรองรับ 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)

3
มันอาจถูกลดระดับลงเนื่องจาก isnan () ใช้เวลาลอยไม่ใช่สตริง ไม่มีอะไรผิดปกติกับฟังก์ชั่นและปัญหาก็คือเมื่อเขาพยายามใช้มัน (สำหรับกรณีการใช้งานเฉพาะนั้นทางออกของเขานั้นใช้ได้ แต่ก็ไม่ใช่คำตอบสำหรับคำถามนี้)
Peter Hansen

6
ระวังการตรวจสอบประเภทด้วยวิธีนี้ สิ่งนี้จะไม่ทำงานเช่นสำหรับ numpy.float32 NaN ดีกว่าที่จะลองใช้ / ยกเว้นโครงสร้าง: def is_nan(x): try: return math.isnan(x) except: return False
Rob

3
NaN ไม่ได้หมายความว่าค่าไม่ใช่หมายเลขที่ถูกต้อง มันเป็นส่วนหนึ่งของการเป็นตัวแทนจุดลอย IEEE เพื่อระบุว่าผลลัพธ์ที่เฉพาะเจาะจงไม่ได้กำหนด เช่น 0/0 ดังนั้นการถามว่า "hello" เป็นน่านนั้นไร้ความหมายหรือไม่
Brice M. Dempsey

2
สิ่งนี้จะดีกว่าเพราะ NaN สามารถลงจอดในรายการใด ๆ ของสตริง ints หรือลอยตรวจสอบที่มีประโยชน์ดังนั้น
RAFIQ

ฉันต้องใช้สิ่งนี้เพื่อจัดการคอลัมน์สตริงในแพนด้า
Cristian Garcia

7

ด้วย 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(เช่นในงูหลามสิ่งที่คุณจะได้รับจากfloat('inf') * 0) และดังนั้นแม้ว่าสตริง 'Hello' ไม่ได้เป็นจำนวน แต่มันก็ไม่ได้NaNเพราะNaNยังคงเป็นค่าตัวเลข!
มาห์ดี

@chwi: คุณถูกต้องหากการจัดการข้อยกเว้นนั้นมีไว้สำหรับข้อยกเว้นเฉพาะ แต่ในคำตอบนี้มีการจัดการข้อยกเว้นทั่วไป ดังนั้นไม่จำเป็นต้องตรวจสอบint(value)ยกเว้นทั้งหมดFalseจะถูกเขียน
Harsha Biyani

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

2

วิธีลบ NaN (float) รายการจากรายการชนิดข้อมูลแบบผสม

หากคุณมีประเภทผสมใน iterable นี่คือวิธีการแก้ปัญหาที่ไม่ได้ใช้ 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จะไม่ถูกเรียกใช้บนค่าที่ไม่ใช่ของประเภท 'ลอย' เมื่อ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

สำหรับน่านชนิดลอย

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

สำหรับสตริงใน panda take 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

สำหรับการลดลงนี้คืออะไร?
Max Kleiner

isnullส่งกลับค่าจริงไม่ใช่แค่ค่า NaN
บอริส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.