防止pandas将'NA'解释为字符串中的NaN

bin*_*ate 48 python pandas

pandas read_csv()方法将'NA'解释为nan(不是数字)而不是有效字符串.

在下面的简单情况中,请注意第1行第2列(基于零的计数)的输出是'nan'而不是'NA'.

sample.tsv(制表符分隔)

PDB CHAIN SP_PRIMARY RES_BEG RES_END PDB_BEG PDB_EN​​D SP_BEG SP_END
5d8b N P60490 1 146 1 146 1 146
5d8b NA P80377 1 126 1 126 1 126
5d8b O P60491 1 118 1 118 1 118

read_sample.py

import pandas as pd

df = pd.read_csv(
    'sample.tsv',
    sep='\t',
    encoding='utf-8',
)

for df_tuples in df.itertuples(index=True):
    print(df_tuples)
Run Code Online (Sandbox Code Playgroud)

产量

(0,u'5d8b',u'N',u'P60490',1,146,1,146,1,146)
(1,u'5d8b',nan,u'P80377',1,126,1 ,
126,1,126 )(2,u'5d8b',u'O',u'P60491',1,118,1,118,1,118)

附加信息

使用"CHAIN"列中的数据引号重写文件,然后使用quotechar参数quotechar='\''具有相同的结果.通过dtype参数传递类型字典dtype=dict(valid_cols)不会改变结果.

防止pandas在read_csv中自动推断类型的旧答案建议首先使用numpy记录数组来解析文件,但是由于现在能够指定列dtypes,因此这不是必需的.

请注意,itertuples()用于保存dtypes,如iterrows文档中所述:"为了在迭代行时保留dtypes,最好使用itertuples(),它返回值的元组,并且通常更快."

在Python 2和3上使用pandas版本0.16.2,0.17.0和0.17.1测试了示例.


有没有办法捕获有效的字符串'NA'而不是转换为nan?

Ant*_*pov 40

您可以使用参数keep_default_nana_values通过手动文档设置所有NA值:

import pandas as pd
from io import StringIO

data = """
PDB CHAIN SP_PRIMARY RES_BEG RES_END PDB_BEG PDB_END SP_BEG SP_END
5d8b N P60490 1 146 1 146 1 146
5d8b NA P80377 _ 126 1 126 1 126
5d8b O P60491 1 118 1 118 1 118
"""

df = pd.read_csv(StringIO(data), sep=' ', keep_default_na=False, na_values=['_'])

In [130]: df
Out[130]:
    PDB CHAIN SP_PRIMARY  RES_BEG  RES_END  PDB_BEG  PDB_END  SP_BEG  SP_END
0  5d8b     N     P60490        1      146        1      146       1     146
1  5d8b    NA     P80377      NaN      126        1      126       1     126
2  5d8b     O     P60491        1      118        1      118       1     118

In [144]: df.CHAIN.apply(type)
Out[144]:
0    <class 'str'>
1    <class 'str'>
2    <class 'str'>
Name: CHAIN, dtype: object
Run Code Online (Sandbox Code Playgroud)

编辑

NA来自na值的所有默认:

默认的NaN识别值是['-1.#IND', '1.#QNAN', '1.#IND', '-1.#QNAN', '#N/A','N/A', 'NA', '#NA', 'NULL', 'NaN', '-NaN', 'nan', '-nan'].虽然默认的NaN值列表中不包含0长度的字符串'',但它仍被视为缺失值.

  • 感谢您提到如何根据需求定制 na 值。我只需要从列表中删除 N/A 和 NA 即可。我需要保留其余的。 (2认同)

小智 32

对我来说,解决方案来自使用参数 na_filter = False

df = pd.read_csv(file_, header=0, dtype=object, na_filter = False)
Run Code Online (Sandbox Code Playgroud)


ars*_*sho 13

设置keep_default_na参数可以解决问题。

这是NA使用 Pandas 读取 CSV 文件时保持字符串值的示例。

data.csv

country_name,country_code
Mexico,MX
Namibia,NA
Run Code Online (Sandbox Code Playgroud)

read_data.py

import pandas as pd
data = pd.read_csv("data.csv", keep_default_na=False)
print(data.describe())
print(data)
Run Code Online (Sandbox Code Playgroud)

输出:

       country_name country_code
count             2            2
unique            2            2
top         Namibia           MX
freq              1            1

  country_name country_code
0       Mexico           MX
1      Namibia           NA
Run Code Online (Sandbox Code Playgroud)

参考:


小智 6

这种方法对我有用:

import pandas as pd
df = pd.read_csv('Test.csv')
co1 col2  col3  col4

a   b    c  d   e
NaN NaN NaN NaN NaN
2   3   4   5   NaN
Run Code Online (Sandbox Code Playgroud)

我复制了该值并创建了一个列表,默认情况下将其解释为 NaN,然后​​注释掉我希望将其解释为非 NaN 的 NA。此方法仍将除 NA 之外的其他值视为 NaN。

 na_values = ["", 
             "#N/A", 
             "#N/A N/A", 
             "#NA", 
             "-1.#IND", 
             "-1.#QNAN", 
             "-NaN", 
             "-nan", 
             "1.#IND", 
             "1.#QNAN", 
             "<NA>", 
             "N/A", 
#              "NA", 
             "NULL", 
             "NaN", 
             "n/a", 
             "nan", 
             "null"]

df1 = pd.read_csv('Test.csv',na_values=na_values,keep_default_na=False )

      co1  col2  col3  col4
a     b     c     d     e
NaN  NA   NaN    NA   NaN
2     3     4     5   NaN
Run Code Online (Sandbox Code Playgroud)


Jon*_*Jon 6

以Anton Protopopov答案为基础,这是一种最小化修改默认值的干净方法(即删除您不希望解析为 NaN 的值并添加您希望解析为 NaN 的值):

from pandas._libs.parsers import STR_NA_VALUES

accepted_na_values = STR_NA_VALUES - {'NA'} | {'_'}
path = 'myexcel.xlsx'
df = pd.read_excel(path, keep_default_na=False, na_values=accepted_na_values)
Run Code Online (Sandbox Code Playgroud)