2013-02-26 5 views
9

Ich möchte eine riesige Textdatei lesen, die Liste von Listen von ganzen Zahlen enthält. Jetzt mache ich folgendes:Der schnellste Weg, um Eingaben in Python zu lesen

G = [] 
with open("test.txt", 'r') as f: 
    for line in f: 
     G.append(list(map(int,line.split()))) 

Allerdings dauert es etwa 17 Sekunden (via timeit). Gibt es eine Möglichkeit, diese Zeit zu reduzieren? Vielleicht gibt es eine Möglichkeit, die Karte nicht zu verwenden.

+0

Versuchen Liste-Verständnis. –

+4

Gibt es einen Grund, "numpy" hier nicht zu verwenden? – DSM

+3

Definieren Sie "riesig". Hat jede Zeile die gleiche Anzahl von ganzen Zahlen? –

Antwort

0

wäre die einfachste Speedup für PyPy http://pypy.org/

Die nächste Ausgabe gehen überhaupt nicht um die Datei zu lesen (wenn möglich). Bearbeite es stattdessen wie einen Stream.

0

Listenübersichten sind oft schneller.

G = [[int(item) item in line.split()] for line in f] 

Darüber hinaus versuchen PyPy und Cython und numpy

+0

'G = [map (int, line.split()) für Zeile in f]' ist schneller. –

+0

@StevenRumbalski Diese Zeile erzeugt Kartenobjekte: '[, , ...'. Aber @ forivall Linie funktioniert. –

+0

@BranAlgue. Aha! Sie verwenden Python 3. Ändern Sie das also in 'G = [list (map (int, line.split())) für Zeile in f]'. Es ist immer noch schneller als das geschachtelte Listenverständnis. –

0

Sie können auch die Daten in eine Datenbank über Bulk-Einsatz zu bringen versuchen, dann mit Set-Operationen der Bearbeitung Ihrer Aufzeichnungen. Je nachdem, was Sie tun müssen, ist dies möglicherweise schneller, da die Bulk-Insert-Software für diese Art von Aufgabe optimiert ist.

1

Als allgemeine Faustregel (für fast jede Sprache) wird die Verwendung von read() zum Einlesen der gesamten Datei schneller sein als das Lesen jeweils einer Zeile. Wenn Sie nicht durch den Speicher eingeschränkt sind, lesen Sie die gesamte Datei auf einmal und teilen Sie dann die Daten in Zeilenumbrüche auf, und durchlaufen Sie dann die Liste der Zeilen.

22

numpy hat die Funktionen loadtxt und genfromtxt, aber keiner ist besonders schnell. Einer der schnellsten Textleser, der in einer weit verbreiteten Bibliothek verfügbar ist, ist die read_csv-Funktion in pandas (http://pandas.pydata.org/). Auf meinem Computer dauert das Lesen von 5 Millionen Zeilen mit zwei Ganzzahlen pro Zeile etwa 46 Sekunden mit , 26 Sekunden mit numpy.genfromtxt und etwas mehr als 1 Sekunde mit pandas.read_csv.

Hier ist die Sitzung mit dem Ergebnis. (Dies ist unter Linux, Ubuntu 12.04 64 Bit. Sie können es hier nicht sehen, aber nach jedem Lesen der Datei wurden die Festplatten-Cache gelöscht durch sync; echo 3 > /proc/sys/vm/drop_caches in einer separaten Schale ausgeführt wird.)

In [1]: import pandas as pd 

In [2]: %timeit -n1 -r1 loadtxt('junk.dat') 
1 loops, best of 1: 46.4 s per loop 

In [3]: %timeit -n1 -r1 genfromtxt('junk.dat') 
1 loops, best of 1: 26 s per loop 

In [4]: %timeit -n1 -r1 pd.read_csv('junk.dat', sep=' ', header=None) 
1 loops, best of 1: 1.12 s per loop 
+0

+1, habe deine Antwort nicht gesehen, während ich meine vorbereitet habe. Ich habe gerade die Version des OPs getestet, die auf meinem Rechner etwa 16 Sekunden benötigt. Ich habe auch bemerkt, dass 'loadtxt' langsam ist. Ich bin nicht sicher, warum, ich würde erwarten, dass es schneller ist (und es sollte schneller sein als 'genfromtxt'. Verwenden Sie auch numpy 1.7? – bmu

+0

@bmu: Ja, ich habe numpy 1.7. –

+2

Ich öffnete ein numpy Problem: https://github.com/numpy/numpy/issues/3019 Ich kann mir nicht vorstellen, dass es normal ist, dass 'loadtxt' so langsam ist. – bmu

5

pandas die basiert auf numpy hat eine C basiert file parser die sehr schnell ist:

# generate some integer data (5 M rows, two cols) and write it to file 
In [24]: data = np.random.randint(1000, size=(5 * 10**6, 2)) 

In [25]: np.savetxt('testfile.txt', data, delimiter=' ', fmt='%d') 

# your way 
In [26]: def your_way(filename): 
    ...:  G = [] 
    ...:  with open(filename, 'r') as f: 
    ...:   for line in f: 
    ...:    G.append(list(map(int, line.split(',')))) 
    ...:  return G   
    ...: 

In [26]: %timeit your_way('testfile.txt', ' ') 
1 loops, best of 3: 16.2 s per loop 

In [27]: %timeit pd.read_csv('testfile.txt', delimiter=' ', dtype=int) 
1 loops, best of 3: 1.57 s per loop 

So pandas.read_csv etwa eineinhalb Sekunden braucht, um Ihre Daten zu lesen und ist etwa 10-mal schneller als Ihre Methode.