如何将 NULL 视为带有 pandas 的普通字符串?

Posted

技术标签:

【中文标题】如何将 NULL 视为带有 pandas 的普通字符串?【英文标题】:How to treat NULL as a normal string with pandas? 【发布时间】:2018-11-13 23:26:49 【问题描述】:

我有一个带有字符串列的 csv 文件,我想用 pandas 读取它。在此文件中,字符串null 作为实际值出现,不应视为缺失值。

例子:

import pandas as pd
from io import StringIO

data = u'strings,numbers\nfoo,1\nbar,2\nnull,3'
print(pd.read_csv(StringIO(data)))

这给出了以下输出:

  strings  numbers
0     foo        1
1     bar        2
2     NaN        3

我该怎么做才能将值 null 原样(而不是 NaN)放入 DataFrame?可以假定该文件不包含任何实际缺失的值。

【问题讨论】:

无法重现该问题。它给了我null 作为一个字符串。 @HarvIpan 当我运行他们的代码时,它给出了 NaN,正如 OP 所说的那样......嗯 @coldspeed,有趣..!我想知道我做错了什么。无论如何,你的答案很好。 ~+1。 我使用 pandas 0.23.0 和 python 3.5.2,如果有帮助的话...... @coldspeed,仅供参考,我已经扭转了这个问题,这个问题现在针对this old one。同样的问题,但现在这里的答案可能更好。 【参考方案1】:

您可以为string 列指定converters 参数。

pd.read_csv(StringIO(data), converters='strings' : str)

  strings  numbers
0     foo        1
1     bar        2
2    null        3

这将绕过 pandas 的自动解析。


另一个选项是设置na_filter=False:

pd.read_csv(StringIO(data), na_filter=False)

  strings  numbers
0     foo        1
1     bar        2
2    null        3

这适用于整个 DataFrame,因此请谨慎使用。如果您想通过手术将其应用于选择列,我建议您使用第一个选项。

【讨论】:

【参考方案2】:

发生这种情况的原因是字符串'null'在解析时被视为NaN,除了@coldspeed的答案之外,您还可以通过keep_default_na=False来关闭它:

In[49]:
data = u'strings,numbers\nfoo,1\nbar,2\nnull,3'
df = pd.read_csv(io.StringIO(data), keep_default_na=False)
df

Out[49]: 
  strings  numbers
0     foo        1
1     bar        2
2    null        3

完整列表是:

na_values : 标量、str、list-like 或 dict,默认无

识别为 NA/NaN 的附加字符串。如果dict通过,具体 每列 NA 值。默认情况下,解释以下值 作为 NaN:''、'#N/A'、'#N/A N/A'、'#NA'、'-1.#IND'、'-1.#QNAN'、'-NaN'、 '-nan'、'1.#IND'、'1.#QNAN'、'N/A'、'NA'、'NULL'、'NaN'、'n/a'、'nan'、 ‘空’。

【讨论】:

有趣的是他们有多个参数来做完全相同的事情...... @coldspeed 是的,你有不同的副作用取决于是否指定了 na_values,这会使事情变得更加复杂【参考方案3】:

更新:2020-03-23 for Pandas 1+:

非常感谢 @aiguofer 提供的适应解决方案:

na_vals = pd.io.parsers.STR_NA_VALUES.difference('NULL','null')
df = pd.read_csv(io.StringIO(data), na_values=na_vals, keep_default_na=False)

旧答案:

我们可以从默认_NA_VALUES集合中动态排除'NULL''null'

In [4]: na_vals = pd.io.common._NA_VALUES.difference('NULL','null')

In [5]: na_vals
Out[5]:
'',
 '#N/A',
 '#N/A N/A',
 '#NA',
 '-1.#IND',
 '-1.#QNAN',
 '-NaN',
 '-nan',
 '1.#IND',
 '1.#QNAN',
 'N/A',
 'NA',
 'NaN',
 'n/a',
 'nan'

并在read_csv()中使用它:

df = pd.read_csv(io.StringIO(data), na_values=na_vals)

【讨论】:

谢谢!这几乎可以工作,但你还需要keep_default_na=False,现在默认值在pd.io.parsers.STR_NA_VALUES @aiguofer,非常感谢您指出这一点!我已经相应地改变了答案)【参考方案4】:

其他答案更适合在不将“null”解释为Nan 的情况下读取 csv,但如果您有一个想要“修复”的数据框,则此代码将这样做:df=df.fillna('null')

【讨论】:

以上是关于如何将 NULL 视为带有 pandas 的普通字符串?的主要内容,如果未能解决你的问题,请参考以下文章

像普通列一样访问 Pandas 索引

使用 Python Pandas 对列进行分箱

如何解决 mysqlERROR 1064

如何在使用 Pandas.read_gbq 加载带有列表列的表后恢复结构?

如何将带有 np.arrays 的 Pandas 系列变成数值?

无法在 Pandas 中导入逗号分隔的引用文件