การเปลี่ยนนุ่นหรือ Numpy Nan เป็น None เพื่อใช้กับ MysqlDB


128

ฉันกำลังพยายามเขียนดาต้าเฟรมของ Pandas (หรือสามารถใช้อาร์เรย์ numpy) ไปยังฐานข้อมูล mysql โดยใช้ MysqlDB ดูเหมือนว่า MysqlDB จะไม่เข้าใจ 'nan' และฐานข้อมูลของฉันแสดงข้อผิดพลาดว่า nan ไม่อยู่ในรายการฟิลด์ ฉันต้องหาวิธีแปลง 'nan' เป็น NoneType

ความคิดใด ๆ ?


2
ไม่มีการตั้งค่าใดที่คุณสามารถเปลี่ยนใน Pandas เพื่อให้กลับมาNoneใช้NULLแทนได้nan?
Nathan Hinchey

คำตอบ:


195

@bogatron ถูกต้องคุณสามารถwhereใช้ได้เป็นที่น่าสังเกตว่าคุณสามารถทำสิ่งนี้ได้ในหมีแพนด้า:

df1 = df.where(pd.notnull(df), None)

หมายเหตุ: การเปลี่ยนแปลงนี้ dtype ของคอลัมน์ทั้งหมดobjectไป

ตัวอย่าง:

In [1]: df = pd.DataFrame([1, np.nan])

In [2]: df
Out[2]: 
    0
0   1
1 NaN

In [3]: df1 = df.where(pd.notnull(df), None)

In [4]: df1
Out[4]: 
      0
0     1
1  None

หมายเหตุ: สิ่งที่คุณไม่สามารถสร้าง DataFrames ใหม่dtypeเพื่ออนุญาตประเภทข้อมูลทั้งหมดโดยใช้astypeแล้วfillnaวิธีDataFrame :

df1 = df.astype(object).replace(np.nan, 'None')

แต่น่าเสียดายที่ค่านี้หรือการใช้replaceงานที่มีความNoneเห็นนี้ (ปิด) ปัญหา


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

อย่างไรก็ตามในกรณีเฉพาะนี้ดูเหมือนว่าคุณจะทำ (อย่างน้อยก็ในช่วงเวลาของคำตอบนี้)



1
FWIW .. นี่จะเปลี่ยน dtype ของคอลัมน์เป็น object ด้วยคุณคงไม่สนใจหรอก
Jeff

@ เจฟฟ์ขอบคุณสำหรับลิงค์แปลกฉันหาไม่เจอก่อนหน้านี้! ฉันคิดว่ามันต้องเปลี่ยน dtype เพื่อให้ไม่ต้องพูดถึงแน่นอน!
Andy Hayden

มีประโยชน์ในการใช้งานก่อนที่จะแทรกด้วย Django เพื่อหลีกเลี่ยงการnp.nanถูกแปลงเป็นสตริง"nan"
เงา

ข้อแม้ที่เป็นประโยชน์ ทำให้รู้สึกถึงห่วงผ่านเฉพาะคอลัมน์ที่มีอยู่แล้วdtypeของobjectและทำมันสำหรับผู้ที่จัดการและประเภทอื่น ๆ ที่แตกต่างกันตามความจำเป็น ตามหลักการแล้วfillna(None)จะยอดเยี่ยมมาก
Vishal

84
df = df.replace({np.nan: None})

เครดิตไปที่ผู้ชายคนนี้ที่นี่ในปัญหา Github นี้


5
นี่คือคำตอบที่ดีที่สุดเนื่องจากคุณสามารถใช้df.replace({np.nan: None})เป็นวัตถุชั่วคราวได้
Matt

17

คุณสามารถแทนที่nanด้วยNoneในอาร์เรย์ numpy ของคุณ:

>>> x = np.array([1, np.nan, 3])
>>> y = np.where(np.isnan(x), None, x)
>>> print y
[1.0 None 3.0]
>>> print type(y[1])
<type 'NoneType'>

2
ความกังวลที่อาจเกิดขึ้นเพียงอย่างเดียวคือการเปลี่ยนแปลงของdtype, x.dtypeคือdtype('float64')ในขณะที่เป็นy.dtype dtype('object')
Jaime


4

เพียงเพิ่มเติมจากคำตอบของ @Andy Hayden:

เนื่องจากDataFrame.maskเป็นคู่แฝดที่อยู่ตรงข้ามDataFrame.whereกันพวกเขาจึงมีลายเซ็นเหมือนกัน แต่มีความหมายตรงกันข้าม:

  • DataFrame.whereจะเป็นประโยชน์สำหรับการเปลี่ยนค่าที่เงื่อนไขเป็นเท็จ
  • DataFrame.maskจะใช้สำหรับการเปลี่ยนค่าที่เงื่อนไขเป็นทรู

ดังนั้นในคำถามนี้การใช้งานdf.mask(df.isna(), other=None, inplace=True)อาจจะง่ายกว่า


2

นอกจากนี้อีก: ต้องระวังเมื่อเปลี่ยนหลายแปลงและประเภทของการกลับคอลัมน์จากวัตถุจะลอย ถ้าคุณต้องการเพื่อให้แน่ใจว่าคุณNone's กลับมาจะไม่พลิกnp.NaN' s ใช้ @ ข้อเสนอแนะ pd.whereandy-เฮย์กับการใช้ ภาพประกอบวิธีการแทนที่ยังคง 'ผิด':

In [1]: import pandas as pd

In [2]: import numpy as np

In [3]: df = pd.DataFrame({"a": [1, np.NAN, np.inf]})

In [4]: df
Out[4]:
     a
0  1.0
1  NaN
2  inf

In [5]: df.replace({np.NAN: None})
Out[5]:
      a
0     1
1  None
2   inf

In [6]: df.replace({np.NAN: None, np.inf: None})
Out[6]:
     a
0  1.0
1  NaN
2  NaN

In [7]: df.where((pd.notnull(df)), None).replace({np.inf: None})
Out[7]:
     a
0  1.0
1  NaN
2  NaN

ขอบคุณที่เพิ่มสิ่งนี้ เมื่ออ่านเอกสารอีกครั้งฉันยังไม่เข้าใจพฤติกรรมนี้ อย่างไรก็ตามสิ่งนี้สามารถแก้ไขได้โดยการผูกมัดอีกอันหนึ่ง.replace({np.nan: None})
EliadL

1
replace({np.nan: None})ใช่คุณสามารถจบด้วยการเพิ่มอีก ความคิดเห็นของฉันถูกบันทึกอยู่ในจุดออกอันตรายที่อาจเกิดขึ้นเมื่อเปลี่ยนnp.nan's ข้างต้นทำให้ฉันสะดุด!
gaatjeniksaan

1

ค่อนข้างเก่า แต่ฉันก็พบปัญหาเดียวกัน ลองทำสิ่งนี้:

df['col_replaced'] = df['col_with_npnans'].apply(lambda x: None if np.isnan(x) else x)

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