2016-08-01 14 views
2

Ich habe eine sehr große CSV-Datei, die mehr als 500 Millionen Zeilen hat.Extrahieren von Zeilen aus einer extrem großen (48 GB) CSV-Datei basierend auf Bedingung

Aber Ich brauche nur ein paar tausend Zeilen davon basierend auf einer bestimmten Bedingung. Ich bin zur Zeit mit:

with open('/home/Documents/1681.csv', 'rb') as f: 
    reader = csv.DictReader(f) 
    rows = [row for row in reader if row['flag_central'] == 1] 

Hier ist die Bedingung, dass, wenn die flag_central == 1, ich die Zeile benötigen.

Da die Datei jedoch extrem groß ist, kann ich den obigen Code nicht ausführen. Ich glaube, dass es wegen der for Schleife ist, die ich verwende, die dieses Problem verursacht.

Gibt es auf jeden Fall kann ich diese bestimmten Zeilen aus der CSV-Datei basierend auf der oben genannten Bedingung extrahieren?

+0

Verwenden Sie grep und filtern Sie, was Sie wollen, und es in Python pipe und lesen Sie es als CSV. – YOU

+0

@YOU: Können Sie bitte ein Beispiel als Antwort posten? – ThePredator

+0

Es ist nur ein Hinweis. – YOU

Antwort

2

Wenn dies eine einmalige Aufgabe, würde ich vorschlagen, Unix-Befehle zuerst, dann verarbeiten, um den Extrakt:

cat file | awk -F , '{ if ($5 == "1") print $0 }' > extract.csv 

Dabei steht -F für das Spaltentrennzeichen und 5 für die Spaltennummer. dieses heraus zuerst von

cat file | head -n 1 | tr ',' '\n' | nl | grep flag_central 
=> 
5 flag_central 
^ this is the field number ($5) 

Auf diese Weise werden die Kosten für die Umwandlung der CSV-Datei in Python Objekte zunächst nicht entstehen. Abhängig von Ihrem Anwendungsfall YMMV.

+0

Wie man das oben genannte für mehrere Befehle durchführt? wenn ich eine weitere Bedingung hinzufügen möchte – ThePredator

+0

ist die allgemeine Form der if-Anweisung 'if (Ausdruck) Aktion', wobei 'Ausdruck' eine Kombination von Operationen ist, die entweder wahr (ungleich Null) oder falsch (Null) ergeben. Somit können Sie mehrere Bedingungen unter Verwendung boolescher Operatoren kombinieren, z. 'if ($ 5 ==" 1 "&& $ 1 ==" foo ") ...'. Für komplexere Beispiele schauen Sie bitte [hier] (http://stackoverflow.com/search?q=awk+conditions). Man beachte, wenn die bedingte Logik über einige Terme hinausgeht, z. geschachtelte Bedingungen oder sogar Parsing, würde ich empfehlen, dies als zweiten Schritt in Python zu tun, anstatt ein komplexes awk-Skript zu schreiben. – miraculixx

3

Sie können diese pandas mit tun:

import pandas as pd 

chunk_list=[] 
for chunk in pd.read_csv('/home/Documents/1681.csv', chunksize=10000): 
    chunk_list.append(chunk[chunk['flag_central'] == 1]` 

final_df = pd.concat(chunk_list) 

Grundsätzlich ist dieser 10000 Zeilen gleichzeitig gelesen werden und filtern Sie die Zeilen, die diese nicht Ihre Bedingung erfüllen, erhalten eine Liste angehängt und wenn Sie fertig sind die Brocken werden zu einem endgültigen Datenrahmen verkettet

+0

Ich bekomme den Fehler, 'TypeError: parser_f() hat ein unerwartetes Schlüsselwort Argument 'mode'' – ThePredator

+0

OK der' Modus' ist irrelevant wirklich können Sie es entfernen – EdChum

+0

'final_df', welche Art von Array wird es sein? – ThePredator

2

Sie könnten Pandas verwenden. Die einzige Einschränkung, die ich hätte, wäre, dass Sie mit einer so großen Datei die Datei in Portionen importieren müssten.

import pandas as pd 
tp = pd.read_csv('/home/Documents/1681.csv', iterator=True, chunksize=10000) 
df = pd.concat(tp, ignore_index=True) 

Von dort würden Sie dann in der Lage sein, die Zeile, die Sie in mit Interesse zu extrahieren:

rows = df[df['flag-central'] == 1] 

Wenn Sie diese Sie dann in eine CSV-Datei zurückkehren möchten to_csv verwenden:

rows.to_csv('filename.csv') 
1

Wenn dies ein iterativer Prozess und/oder Sie haben komplexere Bedingungen zu verarbeiten, hier ist ein schneller, Low-Memory-Ansatz in Python, die Sie dort schnell erhalten:

#!/usr/bin/env python 
# put this in parsecsv.py, then chmod +x parsecsv.py 
import sys 
output = lambda l: sys.stdout.write(l) 
for line in sys.stdin: 
    fields = line.split(',') 
    # add your conditions below 
    # call output(line) to output 
    if fields[0] == "foo": 
     output(line) 

Dies sollen als Pipeline-Filter aus der Befehlszeile verwendet werden:

$ cat file | parsecsv > extract.csv 

Eigentlich habe ich ein etwas generic & maintainable template, die Ihnen nützlich sein könnten.

Verwandte Themen