574 Stimmen

Pandas read_csv: low_memory und dtype Optionen

df = pd.read_csv('somefile.csv')

...gibt einen Fehler:

.../site-packages/pandas/io/parsers.py:1130: DtypeWarning: Spalten (4,5,7,16) haben gemischte Typen. Geben Sie die dtype-Option beim Import an oder setzen Sie low_memory=False.

Warum steht die dtype-Option in Verbindung mit low_memory, und warum könnte low_memory=False helfen?

718voto

firelynx Punkte 28306

Die veraltete Low_memory-Option

Die low_memory-Option ist nicht ordnungsgemäß veraltet, sollte es aber sein, da sie tatsächlich nichts anders macht[Quelle]

Der Grund, warum Sie diese low_memory-Warnung erhalten, liegt darin, dass das Raten von Dtypen für jede Spalte sehr speicherintensiv ist. Pandas versucht herauszufinden, welchen Dtyp er setzen soll, indem es die Daten in jeder Spalte analysiert.

Dtyp-Raten (sehr schlecht)

Pandas kann nur bestimmen, welchen Dtyp eine Spalte haben sollte, wenn die gesamte Datei gelesen ist. Das bedeutet, dass nichts wirklich geparst werden kann, bevor die gesamte Datei gelesen ist, es sei denn, man riskiert, den Dtyp dieser Spalte ändern zu müssen, wenn man den letzten Wert liest.

Betrachten Sie das Beispiel einer Datei, in der eine Spalte namens Benutzer-ID vorhanden ist. Es enthält 10 Millionen Zeilen, wobei die Benutzer-ID immer Zahlen sind. Da Pandas nicht wissen kann, dass es nur Zahlen sind, wird es wahrscheinlich als die originalen Zeichenfolgen belassen, bis es die gesamte Datei gelesen hat.

Bestimmen von Dtypen (sollte immer gemacht werden)

hinzufügen

dtype={'user_id': int}

zu dem pd.read_csv()-Aufruf wird Pandas wissen lassen, wenn es mit dem Lesen der Datei beginnt, dass es sich hierbei um Ganzzahlen handelt.

Es ist auch erwähnenswert, dass wenn die letzte Zeile in der Datei in der user_id-Spalte "foobar" geschrieben hätte, das Laden abstürzen würde, wenn der obige Dtyp angegeben wäre.

Beispiel für fehlerhafte Daten, die abstürzen, wenn Dtypen definiert sind

import pandas as pd
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

csvdaten = """user_id,benutzername
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdaten)
pd.read_csv(sio, dtype={"user_id": int, "username": "string"})

ValueError: ungültige Litarale für long() mit Basis 10: 'foobar'

Dtypen sind typischerweise eine numpy-Sache, lesen Sie hier mehr darüber: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html

Welche Dtypen gibt es?

Wir haben Zugriff auf numpy-Dtypen: float, int, bool, timedelta64[ns] und datetime64[ns]. Beachten Sie, dass die numpy-Datum-/Uhrzeit-Dtypen nicht zeitzonenbewusst sind.

Pandas erweitert diesen Satz von Dtypen mit seinen eigenen:

'datetime64[ns, ]' Was ein zeitzonenbewusster Zeitstempel ist.

'category', was im Wesentlichen ein Enum ist (Zeichenfolgen, die durch Ganzzahl-Schlüssel dargestellt werden, um Platz zu sparen

'period[]' Nicht zu verwechseln mit einer Zeitspanne, diese Objekte sind tatsächlich an bestimmte Zeitperioden gebunden

'Sparse', 'Sparse[int]', 'Sparse[float]' ist für spärliche Daten oder 'Daten, die viele Löcher haben' anstatt NaN oder None im DataFrame zu speichern, werden die Objekte weggelassen, um Platz zu sparen.

'Interval' ist ein eigenes Thema, aber sein Hauptzweck ist die Indizierung. Hier erfahren Sie mehr

'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64' sind alles spezifische pandas-Ganzzahlen, die nullfähig sind, im Gegensatz zur numpy-Variante.

'string' ist ein spezifischer Dtyp für die Arbeit mit String-Daten und ermöglicht den Zugriff auf das .str-Attribut der Serie.

'boolean' ist wie das numpy 'bool', unterstützt aber auch fehlende Daten.

Lesen Sie die vollständige Referenz hier:

Pandas-Dtypen-Referenz

Fallen, Einschränkungen, Hinweise

Das Setzen von dtype=object wird die obige Warnung zum Schweigen bringen, macht es aber nicht speicher effizienter, nur prozesseffizienter, wenn überhaupt.

Das Setzen von dtype=unicode wird nichts bewirken, da für numpy ein unicode als object dargestellt wird.

Verwendung von Konvertern

@sparrow weist korrekterweise auf die Verwendung von Konvertern hin, um zu vermeiden, dass Pandas beim Auftreten von 'foobar' in einer als int angegebenen Spalte abstürzt. Ich möchte hinzufügen, dass Konverter wirklich schwerfällig und ineffizient in Pandas sind und als letztes Mittel verwendet werden sollten. Das liegt daran, dass der read_csv-Prozess ein einzelner Prozess ist.

CSV-Dateien können zeilenweise verarbeitet werden und können daher effizienter von mehreren Konvertern parallel verarbeitet werden, indem die Datei einfach in Segmente aufgeteilt und mehrere Prozesse ausgeführt werden, etwas, das von Pandas nicht unterstützt wird. Aber das ist eine andere Geschichte.

79voto

hd1 Punkte 32394

Versuch es:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

Laut der Pandas-Dokumentation:

dtype : Typname oder Dict von Spalte -> Typ

Was low_memory betrifft, ist es standardmäßig True und noch nicht dokumentiert. Ich glaube jedoch nicht, dass das relevant ist. Die Fehlermeldung ist allgemein gehalten, also sollte man sich sowieso nicht mit low_memory befassen müssen. Ich hoffe, das hilft, und lass mich wissen, wenn du weitere Probleme hast

67voto

Neal Punkte 759
df = pd.read_csv('somefile.csv', low_memory=False)

Dies sollte das Problem lösen. Ich habe genau den gleichen Fehler erhalten, als ich 1,8 Millionen Zeilen aus einer CSV-Datei gelesen habe.

32voto

Jerald Achaibar Punkte 477

Dies hat für mich funktioniert!

file = pd.read_csv('example.csv', engine='python')

23voto

sparrow Punkte 9166

Wie bereits von firelynx erwähnt, kann es zu einem Absturz beim Laden kommen, wenn dtype explizit angegeben ist und gemischte Daten vorhanden sind, die nicht mit diesem dtype kompatibel sind. Als Workaround habe ich einen Konverter wie diesen verwendet, um die Werte mit inkombatiblem Datentyp zu ändern, damit die Daten immer noch geladen werden können.

def conv(val):
    if not val:
        return 0    
    try:
        return np.float64(val)
    except:        
        return np.float64(0)

df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X