为什么 pandas.to_csv 在尝试保留 NaN 时会丢弃数字?

Why is pandas.to_csv dropping numbers when trying to preserve NaN?

给定一个 pandas 数据帧

 df = pd.DataFrame([(290122, 0.20, np.nan),
                    (1900, 1.20, "ABC")],
                     columns = ("number", "x", "class")
                  )

     number    x class
 0   290122  0.2   NaN
 1     1900  1.2   ABC

然后将其导出到 csv,我想保留 NaN,例如作为 "NULL" 或 "NaN",

 df.to_csv("df.csv", encoding="utf-8", index=False, na_rep="NULL")

然而,打开 csv 我得到以下信息: 也就是说,第一个单元格中数字的最后两位被删除。

这是在文本编辑器中打开的输出:

 number,x,class
 2901,0.20,NULL
 1900,1.20,ABC

如前所述,当删除 na_rep 参数时,我得到了预期的结果:

 number,x,class
 290122,0.20,
 1900,1.20,ABC

在 .csv 文件中,当从 pandas 读取或写入时 - np.nan 在文件中存储为 ''(空字符串),因此不要使用 na_rep='NULL' 而不是再次从 pandas 读取(保存后),执行此操作:

for col in df.columns:
   df[col].apply(lambda x: np.nan if x == '' else x)

不过,默认情况下,所有空字符串都被读取为 NaN。这仍然有用 - 只是为了安全起见。

我自己以前遇到过这个问题,发现没有其他方法可以解决这个问题,但如果我找到一个(完美地保存 nan 或 NULL),我会在这里更新。

是的,这实际上是 pandas 1.0.0 中的错误。已在 1.0.1 中修复。请参阅发行说明和 https://github.com/pandas-dev/pandas/issues/25099.

根据您的数据,快速解决方法可能是:

import numpy as np
import pandas as pd

na_rep = 'NULL'
if pd.__version__ == '1.0.0':
    na_rep_wrk = 8 * na_rep

data = [(290122, 0.20, 'NULL'), (2**40 - 1, 3.20, 'NULL'), (1900, 1.20, "ABC")]
df = pd.DataFrame(data, columns=("number", "x", "class"))

df.to_csv("df.csv", encoding="utf-8", index=False, na_rep=na_rep_wrk)
df2 = pd.read_csv('df.csv', keep_default_na=False)

assert(np.all(df == df2))

这给出了 csv 文件:

number,x,class
290122,0.2,NULL
109951162777,3.2,NULL
1900,1.2,ABC