用None替换Pandas或Numpy Nan以与MysqlDB一起使用


127

我正在尝试使用MysqlDB将Pandas数据帧(或可以使用numpy数组)写入mysql数据库。MysqlDB似乎不理解'nan',我的数据库抛出一个错误,说nan不在字段列表中。我需要找到一种将'nan'转换为NoneType的方法。

有任何想法吗?


2
您是否可以在Pandas中更改设置以使其返回NoneNULL而不是nan
内森·辛奇

Answers:


194

@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

注意:您不能执行的操作dtype是使用astype,然后使用DataFrame fillna方法来重铸DataFrame 以允许所有数据类型,请执行以下操作:

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

遗憾的是这个没有,也没有使用replace,用作品None这个(关闭)的问题


顺便说一句,值得注意的是,对于大多数用例,您不需要将NaN替换为None,请参阅有关熊猫中NaN和None之间的区别的问题。

但是,在这种特定情况下,您似乎可以这样做(至少在回答此问题时)。



1
FWIW ..这也会将列的dtype更改为object,不过您可能并不在意
Jeff

@Jeff感谢您的链接,很奇怪,我找不到它!我认为必须更改dtype以允许无,绝对值得一提!
安迪·海登

在与Django插入之前使用很有用,以避免np.nan被转换为字符串"nan"
shadi

有用的警告。仅遍历已经dtype存在的那些列object并对其进行处理,并根据需要以不同的方式处理其他类型是有意义的。理想情况下,fillna(None)会很棒。
维沙尔'18


17

您可以在numpy数组中替换nanNone

>>> 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
唯一潜在的问题就是变化dtypex.dtype就是dtype('float64'),虽然y.dtypedtype('object')
Jaime 2013年


4

只是@Andy Hayden的答案的补充:

由于DataFrame.mask是的相对孪生子DataFrame.where,因此它们具有完全相同的签名,但含义相反:

  • DataFrame.where对于替换条件为False的很有用
  • DataFrame.mask用于替换条件为True的值。

所以在这个问题上,使用df.mask(df.isna(), other=None, inplace=True)可能会更直观。


2

另外除了:更换倍数和转换从柱背面的类型时要小心对象浮动。如果您想确定自己None的不会退回到np.NaN's',请使用@ andy-hayden的建议pd.where。替换仍然会出错的说明:

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。以上肯定使我跳了一下!
gaatjeniksaan

1

很老,但我偶然发现了同样的问题。尝试这样做:

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

如果列数据类型为数字则不起作用,因为None不会被转换回nan(pandas 0.23)
shadi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.