Verhindern Sie, dass Pandas 'NA' als NaN in einer Zeichenfolge interpretieren

75

Die Methode pandas read_csv () interpretiert 'NA' als nan (keine Zahl) anstelle einer gültigen Zeichenfolge.

Im folgenden einfachen Fall ist zu beachten, dass die Ausgabe in Zeile 1, Spalte 2 (auf Null basierende Zählung) 'nan' anstelle von 'NA' ist.

sample.tsv ( tabulatorgetrennt )

PDB-KETTE 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 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)

Ausgabe

(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)

zusätzliche Information

Das erneute Schreiben der Datei mit Anführungszeichen für Daten in der Spalte 'CHAIN' und die anschließende Verwendung des Parameters quotechar quotechar='\''führt zum gleichen Ergebnis. Das Übergeben eines Wörterbuchs mit Typen über den Parameter dtype dtype=dict(valid_cols)ändert nichts am Ergebnis.

Eine alte Antwort auf Verhindern, dass Pandas automatisch auf den Typ in read_csv schließen, schlägt vor, zuerst ein numpy-Datensatzarray zum Parsen der Datei zu verwenden. Angesichts der Möglichkeit, jetzt Spalten-dtypes anzugeben, sollte dies jedoch nicht erforderlich sein.

Beachten Sie, dass itertuples () verwendet wird, um dtypes beizubehalten, wie in der iterrows-Dokumentation beschrieben: "Um dtypes beim Durchlaufen der Zeilen beizubehalten, ist es besser, itertuples () zu verwenden, das Tupel der Werte zurückgibt und im Allgemeinen schneller als iterrows ist."

Das Beispiel wurde auf Python 2 und 3 mit den Pandas-Versionen 0.16.2, 0.17.0 und 0.17.1 getestet.


Gibt es eine Möglichkeit, einen gültigen String 'NA' zu erfassen, anstatt ihn in nan umzuwandeln?

binäres Substrat
quelle
Es ist nicht so, dass es als Zahl behandelt wird, sondern zeigt an, dass Sie fehlende Daten haben . Ich weiß nicht, was das Problem in Ihrem Fall ist, aber ich dachte nur, Sie sollten es wissen.
Jeff Mercado
@ JeffMercado Wenn Sie das folgende Beispiel von Anton ausprobieren, aber entfernen keep_default_na=False, werden Sie sehen, dass NaN tatsächlich ist <class 'float'>.
Binarysubstrate
@binarysubstrate Vielleicht können Sie erwägen, Ihre Frage ein wenig zu kürzen (z. B. nur den 'einfachen Fall' beizubehalten), dies würde die Frage fokussierter und nützlicher für andere Leser machen (da es eine sehr gute Frage ist!)
joris
@joris Guter Vorschlag. Ich habe eine Bearbeitung vorgenommen, um die Frage zu vereinfachen und die Länge zu verringern.
Binarysubstrate

Antworten:

66

Sie können Parameter verwenden keep_default_naund na_valuesalle NA-Werte per Hand festlegen :

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

BEARBEITEN

Alle Standardwerte NAvon na-Werten (ab pandas1.0.0):

Die standardmäßig erkannten NaN-Werte sind ['-1. # IND', '1. # QNAN', '1. # IND', '-1. # QNAN', '# N / AN / A', '# N / A ',' N / A ',' n / a ',' NA ',' ',' #NA ',' NULL ',' null ',' NaN ',' -NaN ',' nan ',' - nan ',' '].

Anton Protopopov
quelle
1
Vielen Dank, dass Sie erwähnt haben, wie Sie Na-Werte an unsere Anforderungen anpassen können. Ich musste nur N / A und NA von der Liste entfernen. Ich musste den Rest behalten.
Nitin3685
Danke, du rettest meinen Tag
Romain Norberg
40

Für mich kam die Lösung von der Verwendung von Parametern na_filter = False

df = pd.read_csv(file_, header=0, dtype=object, na_filter = False)
Matthew Coelho
quelle
9

Das Einstellen des keep_default_naParameters reicht aus.

Hier ist ein Beispiel für das Beibehalten eines NAZeichenfolgenwerts beim Lesen einer CSV-Datei mit Pandas.

data.csv::

country_name,country_code
Mexico,MX
Namibia,NA

read_data.py::

import pandas as pd
data = pd.read_csv("data.csv", keep_default_na=False)
print(data.describe())
print(data)

Ausgabe:

       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

Referenz:

Arsho
quelle