2016-07-05 8 views
4

Ich habe eine relativ große (1 GB) Textdatei, die ich durch Addition verschiedene Kategorien in der Größe reduzieren will:Wie zum Streamen in und eine große Datendatei in Python manipuliert

Geography AgeGroup Gender Race Count 
County1 1  M  1 12 
County1 2  M  1 3 
County1 2  M  2 0 

An:

Geography Count 
County1 15 
County2 23 

Dies wäre eine einfache Angelegenheit, wenn die gesamte Datei in den Speicher passen könnte, aber pandas.read_csv() ergibt MemoryError. Also habe ich nach anderen Methoden gesucht, und es scheint viele Optionen zu geben - HDF5? Mit itertools (was kompliziert scheint - Generatoren?) Oder einfach mit den Standard-Datei Methoden in der ersten Geographie (70 Zeilen) zu lesen, summieren Sie die Spalte zählen, und schreiben Sie vor dem Laden in weiteren 70 Zeilen.

Hat jemand irgendwelche Vorschläge für den besten Weg, dies zu tun? Ich mag besonders die Idee, Daten zu streamen, besonders weil ich mir viele andere Orte vorstellen kann, an denen das nützlich wäre. Ich interessiere mich am meisten für diese Methode, oder eine, die ähnlich die grundlegendste Funktionalität verwendet, die möglich ist.

Bearbeiten: In diesem kleinen Fall möchte ich nur die Summen der Zählung nach Geographie. Es wäre jedoch ideal, wenn ich einen Chunk einlesen, eine beliebige Funktion spezifizieren könnte (z. B. 2 Spalten addieren oder das Maximum einer Spalte nach Geografie nehmen), die Funktion anwenden und die Ausgabe vor dem Einlesen eines neuen Chunks schreiben .

+0

Sie wollen also nicht die 3 Spalten in der Mitte? – ayhan

+0

Ich bearbeitet Frage zu klären, danke – HFBrowning

+2

Kennen Sie über [Chunked liest in Pandas] (http://pandas.pydata.org/pandas-docs/stable/io.html#iterating-through-files-chunk-by- Stück)? 'pd.read_csv ('myfile.csv', chunksize = 1000) '. Dann können Sie Teile innerhalb einer Schleife bearbeiten. – chrisaycock

Antwort

9

Sie können dask.dataframe verwenden, die pandas syntaktisch ähnlich ist, aber führt Manipulationen out-of-Core, also Speicher sollte kein Problem sein:

import dask.dataframe as dd 

df = dd.read_csv('my_file.csv') 
df = df.groupby('Geography')['Count'].sum().to_frame() 
df.to_csv('my_output.csv') 

Alternativ, wenn pandas eine Anforderung möglich ist Verwenden Sie Chunked Reads, wie von @ Chrisaycock erwähnt. Vielleicht möchten Sie mit dem Parameter chunksize experimentieren.

# Operate on chunks. 
data = [] 
for chunk in pd.read_csv('my_file.csv', chunksize=10**5): 
    chunk = chunk.groupby('Geography', as_index=False)['Count'].sum() 
    data.append(chunk) 

# Combine the chunked data. 
df = pd.concat(data, ignore_index=True) 
df = df.groupby('Geography')['Count'].sum().to_frame() 
df.to_csv('my_output.csv') 
2

Ich mag Lösung des @ root, aber ich würde etwas weiter die Speichernutzung zu optimieren - nur aggregierte DF im Speicher zu halten und nur die Spalten zu lesen, dass Sie wirklich brauchen:

cols = ['Geography','Count'] 
df = pd.DataFrame() 

chunksize = 2 # adjust it! for example --> 10**5 
for chunk in (pd.read_csv(filename, 
          usecols=cols, 
          chunksize=chunksize) 
      ): 
    # merge previously aggregated DF with a new portion of data and aggregate it again 
    df = (pd.concat([df, 
        chunk.groupby('Geography')['Count'].sum().to_frame()]) 
      .groupby(level=0)['Count'] 
      .sum() 
      .to_frame() 
     ) 

df.reset_index().to_csv('c:/temp/result.csv', index=False) 

Testdaten :

Geography,AgeGroup,Gender,Race,Count 
County1,1,M,1,12 
County2,2,M,1,3 
County3,2,M,2,0 
County1,1,M,1,12 
County2,2,M,1,33 
County3,2,M,2,11 
County1,1,M,1,12 
County2,2,M,1,111 
County3,2,M,2,1111 
County5,1,M,1,12 
County6,2,M,1,33 
County7,2,M,2,11 
County5,1,M,1,12 
County8,2,M,1,111 
County9,2,M,2,1111 

output.csv:

Geography,Count 
County1,36 
County2,147 
County3,1122 
County5,24 
County6,33 
County7,11 
County8,111 
County9,1111 

PS mit diesem Ansatz können Sie große Dateien verarbeiten.

PPS Chunking Ansatz sollte funktionieren, wenn Sie Ihre Daten sortieren müssen - in diesem Fall würde ich klassische UNIX-Tools verwenden, wie awk, sort, etc. für Ihre Daten zuerst

Sortierung Ich würde empfehlen, auch zu verwenden PyTables (HDF5 Storage), anstelle von CSV-Dateien - es ist sehr schnell und ermöglicht das Lesen von Daten bedingt (mit where Parameter), so ist es sehr praktisch und spart eine Menge Ressourcen und in der Regel much faster im Vergleich zu CSV.