Speicherfehler bei Verwendung von pandas read_csv


79

Ich versuche etwas ziemlich Einfaches zu tun, indem ich eine große CSV-Datei in einen Pandas-Datenrahmen lese.

data = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2)

Der Code schlägt entweder mit a fehl MemoryErroroder wird einfach nie beendet.

Die Mem-Nutzung im Task-Manager wurde bei 506 MB gestoppt, und nach 5 Minuten ohne Änderung und ohne CPU-Aktivität habe ich sie gestoppt.

Ich benutze Pandas Version 0.11.0.

Mir ist bekannt, dass es früher ein Speicherproblem mit dem Datei-Parser gab, aber laut http://wesmckinney.com/blog/?p=543 sollte dies behoben sein.

Die Datei, die ich zu lesen versuche, ist 366 MB groß. Der obige Code funktioniert, wenn ich die Datei auf etwas Kurzes (25 MB) reduziere.

Es ist auch passiert, dass ich ein Popup bekomme, das mir sagt, dass es nicht an die Adresse 0x1e0baf93 schreiben kann ...

Stacktrace:

Traceback (most recent call last):
  File "F:\QA ALM\Python\new WIM data\new WIM data\new_WIM_data.py", line 25, in
 <module>
    wimdata = pandas.read_csv(filepath, header = 0, sep = DELIMITER,skiprows = 2
)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 401, in parser_f
    return _read(filepath_or_buffer, kwds)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 216, in _read
    return parser.read()
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\io\parsers.py"
, line 643, in read
    df = DataFrame(col_dict, columns=columns, index=index)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 394, in __init__
    mgr = self._init_dict(data, index, columns, dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 525, in _init_dict
    dtype=dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\frame.py"
, line 5338, in _arrays_to_mgr
    return create_block_manager_from_arrays(arrays, arr_names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1820, in create_block_manager_from_arrays
    blocks = form_blocks(arrays, names, axes)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1872, in form_blocks
    float_blocks = _multi_blockify(float_items, items)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1930, in _multi_blockify
    block_items, values = _stack_arrays(list(tup_block), ref_items, dtype)
  File "C:\Program Files\Python\Anaconda\lib\site-packages\pandas\core\internals
.py", line 1962, in _stack_arrays
    stacked = np.empty(shape, dtype=dtype)
MemoryError
Press any key to continue . . .

Ein bisschen Hintergrundwissen - Ich versuche, die Leute davon zu überzeugen, dass Python dasselbe wie R kann. Dazu versuche ich, ein R-Skript zu replizieren, das dies tut

data <- read.table(paste(INPUTDIR,config[i,]$TOEXTRACT,sep=""), HASHEADER, DELIMITER,skip=2,fill=TRUE)

R schafft es nicht nur, die obige Datei einwandfrei zu lesen, sondern liest sogar mehrere dieser Dateien in einer for-Schleife (und macht dann einige Dinge mit den Daten). Wenn Python ein Problem mit Dateien dieser Größe hat, könnte ich einen verlorenen Kampf führen ...


1
Auf jeden Fall sollten Pandas keine Probleme mit CSVs dieser Größe haben. Können Sie diese Datei online veröffentlichen?
Andy Hayden

1
Sie können auch versuchen, nrows=something smallzu übergeben read_csv, um sicherzustellen, dass nicht die Größe der Datei Probleme verursacht, was, wie Andy sagte, nicht der Fall sein sollte.
TomAugspurger

1
Es könnte etwas mit "Visual Studio, mit Anaconda und PTVS" zu tun haben ... vielleicht versuchen Sie es auch mit normalem Python
Andy Hayden

3
Ich habe Folgendes gefunden, um das Problem zu lösen: Lesen Sie die CSV als Chunks csv_chunks = pandas.read_csv(filepath, sep = DELIMITER,skiprows = 1, chunksize = 10000)und verketten Sie dann die Chunks df = pandas.concat(chunk for chunk in csv_chunks). Ich bin immer noch daran interessiert zu wissen, warum das Lesen auf einmal nicht funktioniert. Für mich scheint dies ein Problem mit dem CSV-Reader zu sein.
Anne

11
Wenn jemand dies noch verfolgt, habe ich ein kleines Update. Ich bin zu der Überzeugung gelangt, dass der CSV-Parser in Ordnung ist (und auch sehr schnell), aber beim Erstellen von Datenrahmen gibt es ein Speicherproblem. Der Grund, warum ich das glaube: Wenn ich den chunksize=1000Hack verwende, um die CSV zu lesen, und dann versuche, alle Chunks zu einem großen Datenrahmen zu verketten, explodiert an diesem Punkt der Speicher mit einem etwa 3-4-fachen Speicherbedarf im Vergleich zur Größe der Originaldatei. Hat jemand eine Idee, warum der Datenrahmen explodieren könnte?
Anne

Antworten:


31

Windows-Speicherbeschränkung

Speicherfehler treten bei Python häufig auf, wenn die 32-Bit-Version unter Windows verwendet wird. Dies liegt daran, dass 32-Bit-Prozesse standardmäßig nur 2 GB Speicher zum Spielen erhalten .

Tricks zur Reduzierung der Speichernutzung

Wenn Sie in Windows kein 32-Bit-Python verwenden, aber beim Lesen von CSV-Dateien die Speichereffizienz verbessern möchten, gibt es einen Trick.

Die Funktion pandas.read_csv verwendet eine Option namens dtype. Auf diese Weise erfahren Pandas, welche Typen in Ihren CSV-Daten vorhanden sind.

Wie das funktioniert

Standardmäßig versuchen Pandas zu erraten, welche dtypes Ihre CSV-Datei hat. Dies ist eine sehr schwere Operation, da während der Bestimmung des d-Typs alle Rohdaten als Objekte (Zeichenfolgen) im Speicher gehalten werden müssen.

Beispiel

Angenommen, Ihre CSV sieht folgendermaßen aus:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01

Dieses Beispiel ist natürlich kein Problem beim Einlesen in den Speicher, aber es ist nur ein Beispiel.

Wenn Pandas die obige CSV-Datei ohne dtype-Option lesen würden, würde das Alter als Zeichenfolge im Speicher gespeichert, bis Pandas genügend Zeilen der CSV-Datei gelesen hat, um eine qualifizierte Vermutung anzustellen.

Ich denke, die Standardeinstellung bei Pandas ist das Lesen von 1.000.000 Zeilen, bevor der dtype erraten wird.

Lösung

Indem Sie dtype={'age':int}als Option für das .read_csv()Testament angeben, lassen Sie Pandas wissen, dass das Alter als Zahl interpretiert werden sollte. Das spart Ihnen viel Speicher.

Problem mit beschädigten Daten

Wenn Ihre CSV-Datei jedoch wie folgt beschädigt wäre:

name, age, birthday
Alice, 30, 1985-01-01
Bob, 35, 1980-01-01
Charlie, 25, 1990-01-01
Dennis, 40+, None-Ur-Bz

Wenn Sie dann angeben, dtype={'age':int}wird der .read_csv()Befehl unterbrochen, da er nicht "40+"in int umgewandelt werden kann. Bereinigen Sie Ihre Daten also sorgfältig!

Hier können Sie sehen, wie viel höher die Speichernutzung eines Pandas-Datenrahmens ist, wenn Floats als Zeichenfolgen beibehalten werden:

Versuch es selber

df = pd.DataFrame(pd.np.random.choice(['1.0', '0.6666667', '150000.1'],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 224544 (~224 MB)

df = pd.DataFrame(pd.np.random.choice([1.0, 0.6666667, 150000.1],(100000, 10)))
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
# 79560 (~79 MB)

Ich kann sehen, wie dies das Lesen der Daten beschleunigen kann, aber den Speicher verringert. Sicherlich sollte es nicht mehr als ein paar Zeichenfolgenwerte pro Spalte speichern müssen, um den Datentyp zu erraten? Das heißt, es sei denn, Sie haben eine Unmenge von Spalten oder die read_csvFunktion macht etwas unglaublich Funky, wäre ich sehr überrascht, wenn die Speichernutzung merklich höher ist.
Hannes Ovrén

2
@ HannesOvrén Der Datentyp kann nicht erraten werden, bevor Sie einen wesentlichen Teil der Daten gelesen haben. Andernfalls besteht die Gefahr, dass Sie ihn mehrmals ändern müssen, was die Kosten erhöht. Ich denke, Pandas lesen standardmäßig die ersten Millionen Zeilen, bevor sie raten. Ich habe das Speicherprofil unseres Pandas-basierten Produkts um das 50-fache reduziert, indem ich ds-Typen zu CSV-Lasten hinzugefügt habe.
Firelynx

1
Hmm, wenn ich darüber nachdenke, könnte es problematisch sein zu entscheiden, ob "3" ein Float oder Int sein wird, es sei denn, Sie sehen irgendwo auch eine "2.5". Danke für die Erklärung. Ich wusste nichts davon.
Hannes Ovrén

Das ist nicht wahr. Mit dtype ist und im Speicher teurer und zeitlich langsamer. 6 mal mit dtype in read_csv getestet. Die Durchschnittswerte sind: ... Speicher Nr. Typ: 12.121.429,3333333334 | Speicher mit dtype: 12,124,160.0 ... In 13-mal getesteter Zeit sind die Durchschnittswerte: ... Zeit keine dtypes: 2.0494697460761437 | Zeit mit dtypes: 2.100334332539485 ... Verwendet: import os import psutil process = psutil.Process (os.getpid ()) print (process.memory_info (). rss) ___Datenzeilen: 1,5 Millionen aus drei getrennten Datensätzen, Spalten 90% sind Objekttyp. * Offensichtlich hat float weniger Größe als String-Typ
nikolaosmparoutis

@nikolaos_mparoutis Ich bin mir nicht sicher, wie Sie zu diesen Ergebnissen gekommen sind. Vielleicht möchten Sie Ihre eigene Antwort schreiben, weil es schwierig ist, dem Code und dem Kommentar in Ihrem Kommentar zu folgen. Meine Antwort ist ziemlich alt, vielleicht hat sich etwas geändert.
Firelynx

6

Ich hatte das gleiche Speicherproblem beim einfachen Lesen einer durch Tabulatoren getrennten Textdatei mit einer Größe von etwa 1 GB (über 5,5 Millionen Datensätze) und dies löste das Speicherproblem:

df = pd.read_csv(myfile,sep='\t') # didn't work, memory error
df = pd.read_csv(myfile,sep='\t',low_memory=False) # worked fine and in less than 30 seconds

Spyder 3.2.3 Python 2.7.13 64 Bit


7
Es ist nicht low_memory=False
intuitiv

2

Ich verwende Pandas auf meiner Linux-Box und habe viele Speicherlecks festgestellt, die erst behoben wurden, nachdem Pandas nach dem Klonen von Github auf die neueste Version aktualisiert wurde.


1

Dieses Problem trat auch auf, wenn ich in einer virtuellen Maschine ausgeführt wurde oder an einem anderen Ort, an dem der Speicher stark eingeschränkt ist. Es hat nichts mit Pandas oder Numpy oder CSV zu tun, wird aber immer dann auftreten, wenn Sie versuchen, mehr Speicher zu verwenden, als Sie verwenden dürfen, nicht einmal nur in Python.

Die einzige Chance, die Sie haben, ist das, was Sie bereits versucht haben. Versuchen Sie, das große Ding in kleinere Stücke zu zerlegen, die in die Erinnerung passen.

Wenn Sie sich jemals gefragt haben, worum es bei MapReduce geht, haben Sie es selbst herausgefunden ... MapReduce würde versuchen, die Chunks auf viele Maschinen zu verteilen, und Sie würden versuchen, die Chunke nacheinander auf einer Maschine zu verarbeiten.

Was Sie bei der Verkettung der Chunk-Dateien herausgefunden haben, könnte in der Tat ein Problem sein, vielleicht wird bei diesem Vorgang eine Kopie benötigt ... aber am Ende erspart dies Ihnen möglicherweise Ihre aktuelle Situation, aber wenn Ihre CSV etwas größer wird Sie könnten wieder gegen diese Wand laufen ...

Es könnte auch sein, dass Pandas so schlau sind, dass sie die einzelnen Datenblöcke tatsächlich nur dann in den Speicher laden, wenn Sie etwas damit tun, wie die Verkettung mit einem großen df?

Verschiedene Dinge, die Sie ausprobieren können:

  • Laden Sie nicht alle Daten auf einmal, sondern teilen Sie sie in Teile auf
  • Soweit ich weiß, kann hdf5 diese Chunks automatisch ausführen und lädt nur den Teil, an dem Ihr Programm gerade arbeitet
  • Wenn die Typen in Ordnung sind, benötigt eine Zeichenfolge '0.111111' mehr Speicher als ein Float
  • Was brauchen Sie eigentlich, wenn die Adresse als Zeichenfolge vorhanden ist, benötigen Sie sie möglicherweise nicht für die numerische Analyse ...
  • Eine Datenbank kann dabei helfen, nur die Teile zu erreichen und zu laden, die Sie tatsächlich benötigen (z. B. nur die 1% aktiven Benutzer).

1

Es gibt keinen Fehler für Pandas 0.12.0 und NumPy 1.8.0.

Ich habe es geschafft, einen großen DataFrame zu erstellen, ihn in einer CSV-Datei zu speichern und ihn dann erfolgreich zu lesen. Bitte sehen Sie das Beispiel hier . Die Größe der Datei beträgt 554 MB (es funktionierte sogar für 1,1-GB-Dateien, dauerte länger, um eine Nutzungshäufigkeit von 1,1-GB-Dateien von 30 Sekunden zu generieren). Obwohl ich 4 GB RAM zur Verfügung habe.

Mein Vorschlag ist, Pandas zu aktualisieren. Eine andere nützliche Sache ist, dass Sie versuchen, Ihr Skript über die Befehlszeile auszuführen, da Sie für R kein Visual Studio verwenden (dies wurde bereits in den Kommentaren zu Ihrer Frage vorgeschlagen), sodass mehr Ressourcen verfügbar sind.


1

Ich habe es chunksizebeim Lesen einer großen CSV-Datei versucht

reader = pd.read_csv(filePath,chunksize=1000000,low_memory=False,header=0)

Das Lesen ist jetzt die Liste. Wir können das wiederholen readerund an die neue CSV schreiben / anhängen oder jede Operation ausführen

for chunk in reader:
    print(newChunk.columns)
    print("Chunk -> File process")
    with open(destination, 'a') as f:
        newChunk.to_csv(f, header=False,sep='\t',index=False)
        print("Chunk appended to the file")

0

Fügen Sie diese hinzu: reviews = pd.read_csv (..., low_memory = False, memory_map = True )

Mein Gedächtnis mit diesen beiden: # 319.082.496 Ohne diese beiden: # 349.110.272


-1

Obwohl dies eine Problemumgehung ist, die weniger als eine Lösung ist, würde ich versuchen, diese CSV in JSON zu konvertieren (sollte trivial sein) und stattdessen eine read_jsonMethode verwenden - ich habe in Pandas beträchtliche JSON / Datenrahmen (100 MB) geschrieben und gelesen Weg ohne Probleme überhaupt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.