216

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

有任何想法吗?

4

14 回答 14

284

@bogatron 说得对,您可以使用where,值得注意的是,您可以在 pandas 中本地执行此操作:

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

注意:您不能重铸 DataFramedtype以允许所有数据类型类型,使用astype,然后使用 DataFramefillna方法:

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

不幸的是,无论是 this 还是 using replace,都不能与Nonesee this (closed) issue一起使用。


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

但是,在这种特定情况下,您似乎这样做了(至少在此答案时)。

于 2013-01-04T19:01:25.247 回答
230
df = df.replace({np.nan: None})

注意:这会将所有受影响的 dtype 更改为object.

这个 Github 问题上感谢这个人。

于 2019-01-28T14:07:22.530 回答
24

您可以在 numpy 数组中替换nan为:None

>>> 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'>
于 2013-01-04T18:57:52.763 回答
18

在跌跌撞撞之后,这对我有用:

df = df.astype(object).where(pd.notnull(df),None)
于 2017-08-02T19:47:59.477 回答
8

另一个补充:替换倍数并将列的类型从object转换回float时要小心。如果您想确定您None的 ' 不会翻转回np.NaN',请使用 using 应用 @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
于 2019-10-10T13:35:17.987 回答
6

只是对@Andy Hayden 回答的补充:

由于DataFrame.mask是 的相反双胞胎DataFrame.where,它们具有完全相同的签名但具有相反的含义:

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

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

于 2019-04-29T04:21:44.520 回答
2

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

df['col_replaced'] = df['col_with_npnans'].apply(lambda x: None if np.isnan(x) else x)
于 2016-11-09T14:48:22.423 回答
1

我相信最干净的方法是使用方法中的na_value参数pandas.DataFrame.to_numpy()文档):

na_value : 任意,可选

用于缺失值的值。默认值取决于 dtype 和 DataFrame 列的 dtypes。

1.1.0 版中的新功能。

例如,您可以使用将 NaN 替换为 None 的字典转换为

columns = df.columns.tolist()
dicts_with_nan_replaced = [
    dict(zip(columns, x))
    for x in df.to_numpy(na_value=None)
]
于 2021-07-13T12:51:09.413 回答
1

replace np.nanwith在不同版本的 pandas 中None以不同的方式完成:

if version.parse(pd.__version__) >= version.parse('1.3.0'):
    df = df.replace({np.nan: None})
else:
    df = df.where(pd.notnull(df), None)

这解决了对于 pandas 版本 <1.3.0 的问题,如果其中的值df已经存在,None那么df.replace({np.nan: None})会将它们切换回np.nan!

于 2022-01-26T11:37:27.583 回答
0

您是否有要偶然查看的代码块?

使用.loc,pandas 可以根据逻辑条件(过滤)访问记录并对其进行操作(使用 = 时)。将.loc掩码设置为某个值将就地更改返回数组(所以在这里要小心;我建议在代码块中使用之前对 df 副本进行测试)。

df.loc[df['SomeColumn'].isna(), 'SomeColumn'] = None

外部函数是df.loc[row_label, column_label] = None。我们将使用.isna()方法为 row_label 使用布尔掩码,在SomeColumn列中查找“NoneType”值。

我们将使用.isna()方法返回SomeColumn列中的行/记录的布尔数组作为我们的row_labeldf['SomeColumn'].isna()。它将隔离SomeColumn具有 Pandas 使用.isna()方法检查的任何“NoneType”项目的所有行。

我们将在为 row_label 屏蔽数据框时使用 column_label,并为.loc掩码标识我们想要操作的列。

最后,我们将.loc掩码设置为None,因此返回的行/记录根据掩码索引更改为None 。

以下是有关.loc.isna()的 pandas 文档的链接。

参考资料:
https ://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.isna.html

于 2021-10-05T19:52:34.913 回答
0

在用 where 语句替换之前将 numpy NaN 转换为 pandas NA:

df = df.replace(np.NaN, pd.NA).where(df.notnull(), None)
于 2021-12-01T07:07:55.690 回答
0

在将 Pandas 更新到 1.3.2 后发现推荐的答案和替代建议都不适用于我的应用程序后,我采用蛮力方法解决了安全问题:

buf = df.to_json(orient='records')
recs = json.loads(buf)
于 2021-12-02T20:16:35.867 回答
0

还有另一种选择,这实际上对我有用:

df = df.astype(object).replace(np.nan, None)
于 2022-03-04T15:35:57.880 回答
-2

这对我有用:

df = df.fillna(0)
于 2021-11-25T13:54:49.957 回答