อะไรคือความแตกต่างระหว่าง NaN และ None?


97

ฉันกำลังอ่านสองคอลัมน์ของไฟล์ csv โดยใช้แพนด้าreadcsv()จากนั้นกำหนดค่าให้กับพจนานุกรม คอลัมน์ประกอบด้วยสตริงของตัวเลขและตัวอักษร ในบางครั้งมีกรณีที่เซลล์ว่างเปล่า ในความคิดของฉันค่าที่อ่านในรายการพจนานุกรมนั้นควรเป็นNoneแต่nanจะถูกกำหนดให้แทน แน่นอนว่าNoneมีความหมายมากกว่าเซลล์ว่างเนื่องจากมีค่า null ในขณะที่nanบอกว่าค่าที่อ่านไม่ใช่ตัวเลข

ความเข้าใจของฉันถูกต้องหรือไม่อะไรคือความแตกต่างระหว่างNoneและnan? ทำไมจึงnanได้รับมอบหมายแทนNone?

นอกจากนี้พจนานุกรมของฉันตรวจสอบเซลล์ว่างที่ใช้อยู่numpy.isnan():

for k, v in my_dict.iteritems():
    if np.isnan(v):

แต่นี่ทำให้ฉันมีข้อผิดพลาดที่บอกว่าฉันไม่สามารถใช้การตรวจสอบนี้vได้ ฉันเดาว่าเป็นเพราะตัวแปรจำนวนเต็มหรือทศนิยมไม่ใช่สตริงที่ควรใช้ หากเป็นจริงฉันจะตรวจสอบv"เซลล์ว่าง" / nanกรณีได้อย่างไร


ข้อความqwertyไม่ใช่ตัวเลข
Robert Harvey

1
@RobertHarvey ฉันรู้ดังนั้นNoneคงจะเป็นคำอธิบายที่ดีกว่าเกี่ยวกับมูลค่าของเซลล์ว่าง
user1083734

คำตอบ:


110

NaN ถูกใช้เป็นตัวยึดสำหรับข้อมูลที่ขาดหายไปอย่างสม่ำเสมอในหมีแพนด้าความสม่ำเสมอเป็นสิ่งที่ดี ฉันมักจะอ่าน / แปลน่านเป็น"หายไป" นอกจากนี้โปรดดูส่วน"การทำงานกับข้อมูลที่ขาดหายไป"ในเอกสาร

Wes เขียนในเอกสาร'choice of NA-representation' :

หลังจากหลายปีของการใช้งาน [NaN] ได้พิสูจน์แล้วอย่างน้อยก็ในความคิดของฉันว่าเป็นการตัดสินใจที่ดีที่สุดเนื่องจากสถานการณ์ใน NumPy และ Python โดยทั่วไป ค่าพิเศษน่าน (ไม่-A-Number) ถูกนำมาใช้ทุกที่เป็นค่า NA และมีฟังก์ชั่น API isnullและnotnullซึ่งสามารถใช้ข้าม dtypes ในการตรวจสอบค่า NA
...
ดังนั้นฉันจึงเลือกวิธี "การปฏิบัติจริงเอาชนะความบริสุทธิ์" ของ Pythonic และการแลกเปลี่ยนความสามารถ NA จำนวนเต็มสำหรับวิธีการที่ง่ายกว่ามากในการใช้ค่าพิเศษใน float และอาร์เรย์อ็อบเจ็กต์เพื่อแสดงถึง NA และส่งเสริมอาร์เรย์จำนวนเต็มให้ลอยเมื่อต้องเป็น NAs แนะนำ

หมายเหตุ: "gotcha" ว่าจำนวนเต็มซีรีส์ที่มีข้อมูลที่ขาดหายไปเป็น upCast ลอย

ในความคิดของเหตุผลหลักที่จะใช้น่าน (กว่าไม่มี) ก็คือว่ามันจะถูกเก็บไว้กับ numpy ของ dtype float64 มากกว่าวัตถุ dtype มีประสิทธิภาพน้อยลงดูNA พิมพ์โปรโมชั่น

#  without forcing dtype it changes None to NaN!
s_bad = pd.Series([1, None], dtype=object)
s_good = pd.Series([1, np.nan])

In [13]: s_bad.dtype
Out[13]: dtype('O')

In [14]: s_good.dtype
Out[14]: dtype('float64')

ความคิดเห็นของ Jeff (ด้านล่าง) เกี่ยวกับสิ่งนี้:

np.nanอนุญาตให้ดำเนินการแบบเวกเตอร์ มันเป็นค่าลอยในขณะที่Noneตามคำนิยามบังคับประเภทวัตถุซึ่งโดยทั่วไปจะปิดใช้งานประสิทธิภาพทั้งหมดในจำนวน

ทำซ้ำอย่างเร็ว 3 ครั้ง: object == bad, float == good

กล่าวได้ว่าการดำเนินการหลายอย่างอาจยังใช้งานได้ดีกับ None vs NaN (แต่อาจไม่รองรับเช่นบางครั้งอาจให้ผลลัพธ์ที่น่าประหลาดใจ ):

In [15]: s_bad.sum()
Out[15]: 1

In [16]: s_good.sum()
Out[16]: 1.0

เพื่อตอบคำถามที่สอง:
คุณควรใช้pd.isnullและpd.notnullทดสอบข้อมูลที่ขาดหายไป (NaN)


19
เพียงแค่เพิ่ม 2c ที่นี่ .... np.nanอนุญาตให้ใช้งาน vectorized; มันเป็นค่าลอยในขณะที่Noneตามobjectประเภทกองกำลังนิยามและโดยทั่วไปจะปิดการใช้งานประสิทธิภาพทั้งหมดเป็นตัวเลขดังนั้นทำซ้ำอย่างรวดเร็ว 3 ครั้ง:object==bad, float==good
เจฟฟ์

1
คือ<NA>ยังมีnp.nan?
Gathide

18

NaNสามารถใช้เป็นค่าตัวเลขในการดำเนินการทางคณิตศาสตร์ได้ในขณะที่Noneทำไม่ได้ (หรืออย่างน้อยก็ไม่ควร)

NaNเป็นค่าตัวเลขที่กำหนดไว้ในมาตรฐาน IEEE 754 จุดลอยตัวมาตรฐาน Noneเป็นประเภท Python ภายใน ( NoneType) และจะคล้ายกับ "inexistent" หรือ "empty" มากกว่า "numerically invalid" ในบริบทนี้

"อาการ" หลักคือถ้าคุณทำเช่นค่าเฉลี่ยหรือผลรวมในอาร์เรย์ที่มี NaN แม้แต่ตัวเดียวคุณจะได้รับ NaN เป็นผล ...

ในทางกลับกันคุณไม่สามารถดำเนินการทางคณิตศาสตร์โดยใช้Noneเป็นตัวถูกดำเนินการได้

ดังนั้นขึ้นอยู่กับกรณีคุณสามารถใช้Noneเป็นวิธีบอกอัลกอริทึมของคุณไม่ให้พิจารณาค่าที่ไม่ถูกต้องหรือไม่มีอยู่ในการคำนวณ นั่นหมายความว่าอัลกอริทึมควรทดสอบแต่ละค่าเพื่อดูว่าเป็นNoneจริงหรือไม่

Numpy มีฟังก์ชันบางอย่างเพื่อหลีกเลี่ยงค่า NaN ที่จะปนเปื้อนผลลัพธ์ของคุณเช่นnansumและnan_to_numตัวอย่างเช่น


ฉันเห็นด้วยกับคุณว่าไม่ควรใช้สำหรับรายการที่ไม่มีอยู่จริงเหตุใดจึงdf=pd.readcsv('file.csv')ให้NaNค่าเซลล์ว่างแก่ฉันไม่ใช่Noneหรือ เท่าที่ฉันทราบ pd.DataFrames ไม่ได้มีไว้สำหรับตัวเลขเท่านั้น
user1083734

น่าจะเป็นทางเลือกในการออกแบบ ฉันคิดว่า DataFrames และ Series มี a dtypeดังนั้นค่าที่ไม่ถูกต้องของdtype=floatจะต้องแสดงด้วยค่าตัวเลขซึ่งNaNไม่ใช่และNoneไม่ใช่ ( Noneเป็นของNoneType)
heltonbiker

นอกจากนี้วิธีการของ Pandas จำนวนมากยังมีnaข้อโต้แย้งซึ่งช่วยให้คุณตัดสินใจได้ว่าคุณจะใช้ค่าใดเพื่อแทนที่ค่าที่ไม่สามารถใช้ได้
heltonbiker

โอเคขอบคุณ. ดังนั้นฉันจึงไม่ได้อ่านตัวเลขลงใน DataFrame แต่เป็นสตริงของตัวเลขและตัวอักษร ฉันควรใช้การตรวจสอบประเภทใดเพื่อตรวจจับเซลล์ว่าง ตรวจสอบเช่น; ถ้า dtype == float: ??
user1083734

บางทีการโพสต์ตัวอย่างข้อมูล CSV อาจช่วยได้ ฉันนึกภาพออกว่าถ้ามีสตริง dtype จะเป็นสตริงสำหรับทั้งคอลัมน์ (ซีรี่ส์) แต่บางทีถ้าไม่ใช่ทุกแถวที่มีจำนวนคอลัมน์เท่ากันคุณจะได้รับข้อมูลที่ไม่พร้อมใช้งาน ฉันคิดว่าคุณจะต้องตรวจสอบสิ่งนั้น
heltonbiker

3

ฟังก์ชันisnan()จะตรวจสอบว่ามีบางสิ่งเป็น "ไม่ใช่ตัวเลข" หรือไม่และจะส่งคืนตัวแปรเป็นตัวเลขหรือไม่เช่นisnan(2)จะส่งคืนค่าเท็จ

เงื่อนไขmyVar is not Noneจะคืนค่าไม่ว่าจะกำหนดตัวแปรไว้หรือไม่

อาร์เรย์ numpy ของคุณใช้isnan()เนื่องจากมีวัตถุประสงค์เพื่อเป็นอาร์เรย์ของตัวเลขและเริ่มต้นองค์ประกอบทั้งหมดของอาร์เรย์ให้NaNองค์ประกอบเหล่านี้ถือว่า "ว่าง"


1
ฉันคิดว่าisnan(2)จะกลับมาFalseเนื่องจาก 2 ไม่ใช่ NaN
heltonbiker

นอกจากนี้ยังไม่ได้เริ่มต้นค่าอาร์เรย์numpy.empty NaNมันไม่ได้เริ่มต้นค่าเลย
heltonbiker

5
การตรวจสอบที่เหมาะสมสำหรับNone-ness คือไม่myVar is not None myVar != None
ไจ

3
โปรดทราบว่าnp.isnan()ไม่มีการใช้งานสำหรับตัวแปรสตริงดังนั้นหากคุณส่งผ่านสตริงมันจะผิด ดีกว่าที่จะใช้pd.isnullซึ่งใช้ได้กับสตริง
Michael

-1

ด้านล่างนี้คือความแตกต่าง:

  • nan เป็นของชั้นเรียน float
  • None เป็นของชั้นเรียน NoneType

ฉันพบว่าบทความด้านล่างมีประโยชน์มาก: https://medium.com/analytics-vidhya/dealing-with-missing-values-nan-and-none-in-python-6fc9b8fb4f31


แม้ว่าลิงก์นี้อาจตอบคำถามได้ แต่ควรรวมส่วนสำคัญของคำตอบไว้ที่นี่และระบุลิงก์เพื่อการอ้างอิง คำตอบแบบลิงก์เท่านั้นอาจไม่ถูกต้องหากหน้าที่เชื่อมโยงเปลี่ยนไป - จากรีวิว
A.Kootstra

@ A.Kootstra ฉันเข้าใจ
eswara amirthan s

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