Schnellste kostenlose Python-Bibliothek zum Lesen einer CSV-Datei mit 1 bis 3 Zahlenspalten

Ich suche nach der schnellsten Python-Bibliothek, um eine CSV-Datei (wenn das wichtig ist, 1 oder 3 Spalten, alle Ganzzahlen oder Floats, Beispiel ) in ein Python-Array (oder ein Objekt, auf das ich auf ähnliche Weise zugreifen kann, mit einem ähnlichen Zugriffszeit). Es sollte kostenlos sein, unter Windows 7 und Ubuntu 12.04 sowie mit Python 2.7 x64 funktionieren.

CSV mit 1 Spalte:

350
750
252
138
125
125
125
112
95
196
105
101
101
101
102
101
101
102
202
104

CSV mit 3 Spalten:

9,52,1
52,91,0
91,135,0
135,174,0
174,218,0
218,260,0
260,301,0
301,341,0
341,383,0
383,423,0
423,466,0
466,503,0
503,547,0
547,583,0
583,629,0
629,667,0
667,713,0
713,754,0
754,796,0
796,839,1
Zufälligerweise wurde vor 2 Stunden eine sehr ähnliche Frage auf Super User gepostet: superuser.com/q/775893/137286 Die erste Antwort deutet auf eine schnelle Bibliothek hin.
Haben Sie in letzter Zeit mit fastcsv getestet, wie ich unten vorgeschlagen habe? Mich würde sehr interessieren, wie es mit deinen Daten abschneidet. Tschüss, Daniel

Antworten (6)

Also schrieb ich schließlich einen kleinen Benchmark unter Verwendung der Bibliotheken, auf die Steve Barnes hingewiesen hatte. Ich hatte das Gleiche gefunden, als ich danach gesucht hatte, als ich die Frage schrieb, also denke ich, dass dies die wichtigsten sind. Einige andere Ideen, die noch nicht ausprobiert wurden: HDF5 für Python , PyTables , IOPro (nicht kostenlos).

Kurz gesagt, pandas.io.parsers.read_csvschlägt alle anderen, NumPy loadtxtist beeindruckend langsam und NumPy ist from_filebeeindruckend loadschnell.

Daten (ich hätte sie im Benchmark generieren sollen, aber mir läuft gerade die Zeit davon)

Code:

import csv
import os
import cProfile
import time
import numpy
import pandas
import warnings

# Make sure those files in the same folder as benchmark_python.py
# As the name indicates:
# - '1col.csv' is a CSV file with 1 column
# - '3col.csv' is a CSV file with 3 column
filename1 = '1col.csv'
filename3 = '3col.csv'
csv_delimiter = ' '
debug = False

def open_with_python_csv(filename):
    '''
    https://docs.python.org/2/library/csv.html
    '''
    data =[]
    with open(filename, 'rb') as csvfile:
        csvreader = csv.reader(csvfile, delimiter=csv_delimiter, quotechar='|')
        for row in csvreader:
            data.append(row)    
    return data

def open_with_python_csv_cast_as_float(filename):
    '''
    https://docs.python.org/2/library/csv.html
    '''
    data =[]
    with open(filename, 'rb') as csvfile:
        csvreader = csv.reader(csvfile, delimiter=csv_delimiter, quotechar='|')
        for row in csvreader:
            data.append(map(float, row))    
    return data

def open_with_python_csv_list(filename):
    '''
    https://docs.python.org/2/library/csv.html
    '''
    data =[]
    with open(filename, 'rb') as csvfile:
        csvreader = csv.reader(csvfile, delimiter=csv_delimiter, quotechar='|')
        data = list(csvreader)    
    return data


def open_with_numpy_loadtxt(filename):
    '''
    http://stackoverflow.com/questions/4315506/load-csv-into-2d-matrix-with-numpy-for-plotting
    '''
    data = numpy.loadtxt(open(filename,'rb'),delimiter=csv_delimiter,skiprows=0)
    return data

def open_with_pandas_read_csv(filename):
    df = pandas.read_csv(filename, sep=csv_delimiter)
    data = df.values
    return data    


def benchmark(function_name):  
    start_time = time.clock()
    data = function_name(filename1)       
    if debug: print data[0] 
    data = function_name(filename3)
    if debug: print data[0]
    print function_name.__name__ + ': ' + str(time.clock() - start_time), "seconds"


def benchmark_numpy_fromfile():
    '''
    http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html
    Do not rely on the combination of tofile and fromfile for data storage, 
    as the binary files generated are are not platform independent.
    In particular, no byte-order or data-type information is saved.
    Data can be stored in the platform independent .npy format using
    save and load instead.
    
    Note that fromfile will create a one-dimensional array containing your data,
    so you might need to reshape it afterward.
    '''
    #ignore the 'tmpnam is a potential security risk to your program' warning
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', RuntimeWarning)
        fname1 = os.tmpnam()
        fname3 = os.tmpnam()
        
    data = open_with_numpy_loadtxt(filename1)
    if debug: print data[0]
    data.tofile(fname1)
    data = open_with_numpy_loadtxt(filename3)
    if debug: print data[0]
    data.tofile(fname3)
    if debug: print data.shape
    fname3shape = data.shape
    start_time = time.clock()
    data = numpy.fromfile(fname1, dtype=numpy.float64) # you might need to switch to float32. List of types: http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
    if debug: print len(data), data[0], data.shape
    data = numpy.fromfile(fname3, dtype=numpy.float64)
    data = data.reshape(fname3shape)
    if debug: print len(data), data[0], data.shape    
    print 'Numpy fromfile: ' + str(time.clock() - start_time), "seconds"

def benchmark_numpy_save_load():
    '''
    http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html
    Do not rely on the combination of tofile and fromfile for data storage, 
    as the binary files generated are are not platform independent.
    In particular, no byte-order or data-type information is saved.
    Data can be stored in the platform independent .npy format using
    save and load instead.
    
    Note that fromfile will create a one-dimensional array containing your data,
    so you might need to reshape it afterward.
    '''
    #ignore the 'tmpnam is a potential security risk to your program' warning
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', RuntimeWarning)
        fname1 = os.tmpnam()
        fname3 = os.tmpnam()
        
    data = open_with_numpy_loadtxt(filename1)
    if debug: print data[0]    
    numpy.save(fname1, data)    
    data = open_with_numpy_loadtxt(filename3)
    if debug: print data[0]    
    numpy.save(fname3, data)    
    if debug: print data.shape
    fname3shape = data.shape
    start_time = time.clock()
    data = numpy.load(fname1 + '.npy')
    if debug: print len(data), data[0], data.shape
    data = numpy.load(fname3 + '.npy')
    #data = data.reshape(fname3shape)
    if debug: print len(data), data[0], data.shape    
    print 'Numpy load: ' + str(time.clock() - start_time), "seconds"


def main():
    number_of_runs = 20
    results = []
    
    benchmark_functions = ['benchmark(open_with_python_csv)', 
                           'benchmark(open_with_python_csv_list)',
                           'benchmark(open_with_python_csv_cast_as_float)',
                           'benchmark(open_with_numpy_loadtxt)',
                           'benchmark(open_with_pandas_read_csv)',
                           'benchmark_numpy_fromfile()',
                           'benchmark_numpy_save_load()']
    # Compute benchmark
    for run_number in range(number_of_runs):
        run_results = []
        for benchmark_function in benchmark_functions:
            run_results.append(eval(benchmark_function))
            results.append(run_results)
        
    # Display benchmark's results
    print results
    results = numpy.array(results)
    numpy.set_printoptions(precision=10) # http://stackoverflow.com/questions/2891790/pretty-printing-of-numpy-array
    numpy.set_printoptions(suppress=True)  # suppress suppresses the use of scientific notation for small numbers:
    print numpy.mean(results, axis=0)
    print numpy.std(results, axis=0)    
    
    #Another library, but not free: https://store.continuum.io/cshop/iopro/

if __name__ == "__main__":
    #cProfile.run('main()') # if you want to do some profiling
    main()  

Windows 7:

Ausgabe:

open_with_python_csv: 1.57318865672 seconds
open_with_python_csv_list: 1.35567931732 seconds
open_with_python_csv_cast_as_float: 3.0801260484 seconds
open_with_numpy_loadtxt: 14.4942111801 seconds
open_with_pandas_read_csv: 0.371965476805 seconds
Numpy fromfile: 0.0130216095713 seconds
Numpy load: 0.0245501650124 seconds

So installieren Sie alle Bibliotheken: Inoffizielle Windows-Binärdateien für Python-Erweiterungspakete

Windows-Konfiguration:


Ubuntu 12.04:

Ausgabe:

open_with_python_csv: 1.93 seconds
open_with_python_csv_list: 1.52 seconds
open_with_python_csv_cast_as_float: 3.19 seconds
open_with_numpy_loadtxt: 7.47 seconds
open_with_pandas_read_csv: 0.35 seconds
Numpy fromfile: 0.01 seconds
Numpy load: 0.02 seconds

So installieren Sie alle Bibliotheken:

sudo apt-get install python-pip
sudo pip install numpy
sudo pip install pandas

Wenn Bibliotheken bereits installiert sind, aber aktualisiert werden müssen:

sudo apt-get install python-pip
sudo pip install numpy --upgrade
sudo pip install pandas --upgrade

Ubuntu-Konfiguration:

  • Ubuntu 12.04 x64
  • Python 2.7.3
  • NumPy 1.8.1 ( import numpy; numpy.version.version)
  • Pandas 0.14.0 ( import pandas as pd; pd.__version__)

Fühlen Sie sich natürlich frei, den Benchmark zu verbessern, indem Sie kommentieren/bearbeiten/etc. Ich bin mir sicher, dass es viele Dinge zu verbessern gibt:

  • Stellen Sie sicher, dass die aktuellen Ladefunktionen gut optimiert sind
  • Probieren Sie neue Funktionen / Bibliotheken wie HDF5 für Python , PyTables , IOPro (kostenpflichtig) aus.
  • Generieren Sie die CSV im Benchmark (damit man die CSV-Dateien nicht herunterladen muss)
Ein interessanter Ergebnisvergleich.
Du hast mich vor der dunklen und einsamen Welt gerettetnumpy.loadtxt
Gute Antwort. FYI Ich habe Ihren Benchmark auf einer 2-GB-cvs-Datei ausgeführt: open_with_python_csv: 153.789445 Sekunden open_with_python_csv_list: 146.709768 Sekunden open_with_python_csv_cast_as_float: 86.957046 Sekunden open_with_numpy_loadtxt: 157.669637 Sekunden open_with_pandas: 6c.7v_read_read_with_pandas
Das ist großartig und ich habe heute Abend viel aus diesem Beitrag gelernt. Allerdings np.fromfilescheint Ihr furchtbar schnell. Was ich in meinen Tests festgestellt habe, ist, dass es nur in der ersten Zeile funktioniert. Um die gesamte Datei zu bearbeiten, müssen Sie also eine Schleife ausführen, die die Dinge für meine CSV-Datei mit 20.000 Zeilen wieder auf 60 Sekunden verlangsamt, gegenüber 0,75 Sekunden für Pandas. Lesen Sie die gesamte Datei mit np.fromfile? Ich konnte es auch verwenden, np.fromstringindem ich die gesamte csv-Datei geladen habe, replacedie dann '\nmit ''ausgeführt wird np.fromstring. Die String-Manipulationen waren schnell, aber die Konvertierung in Zahlen war langsam. Diese Methode dauerte 2,6 Sekunden.
Versuchen Sie dies 2018 unter Windows 10 mit Python 2.7.13 mit einer Datei mit 100000 Zeilen und 19 Spalten, indem Sie nur open_with_python_csv, open_with_python_csv_list und open_with_pandas_read_csv testen, und die Pandas-Methode ist nicht schneller. Eingebaute CSV-Dateien bedeuten ~0,35 und Pandas ~0,43.
Nur als Hinweis, pandas.read_csv führt standardmäßig eine Menge zufälliger Verarbeitungen durch, wie z ).

Ich möchte hier eine andere Bibliothek beitragen, über die ich bei der Suche nach ähnlichen Fragen gestolpert bin. Ich habe es mit Franck Dernoncourts Benchmark-Code getestet und es schlägt Pythons Standard-CSV und Pandas um Meilen. Ich konnte nicht mit numpy testen, da ich mit einer 24.000-Zeilen-CSV mit Zahlen- und Zeichenfolgenwerten getestet habe.

Diese schnelle Bibliothek basiert tatsächlich auf der Standard-csv-Implementierung und verwendet nur TextIO , wodurch sie schneller wird UND Unicode-Strings korrekt verarbeitet.

Es heißt fastcsv und wurde von Masaya Suzuki entwickelt. Sie können es in GitHub schließen oder Pypi zum Installieren verwenden. Am einfachsten ist:

pip install fastcsv

Auf http://pythonhosted.org/fastcsv/ können Sie mehr Benchmark-Ergebnisse sehen, aber um nur CSV zu lesen, lassen Sie mich ihre Ergebnisse hier wiederholen:

Lese-Benchmark mit fastcsv

Wäre interessant zu wissen, wie sich das mit Ihren Daten verhält.

"TLDR: Dies ist veraltet. Verwenden Sie Python3 und das Standard-csv-Modul. Daher empfehle ich die Verwendung dieser Bibliothek nicht." - Anmerkung des Verfassers?
@SebastianPalma Ursprüngliche Frage gibt Python 2.7 an

Sie haben eine große Auswahl, abhängig von der Datengröße und -komplexität und was Sie mit den resultierenden Daten tun werden:

  1. Die csvBibliothek, die standardmäßig mit Python geliefert wird.
  2. NumPy - numpy.from_file Funktion - Liest in ein NumPy-Array und ist daher sehr leistungsfähig.
  3. Pandas - pandas.io.parsers.read_csv Funktion - liest in einen Pandas-Datenrahmen, ist sehr leistungsfähig und kann riesige Datensätze verarbeiten.

Der erste wird wahrscheinlich schneller zu importieren sein, während die anderen leistungsfähiger sind. Alle sind kostenlos und plattformübergreifend. Die erste ist bereits Teil Ihrer Python-Installation, wenn Sie eine Standardinstallation haben.

Es gibt ein neues pydatatablePaket mit einem sehr schnellen CSV-Reader, der auf der Implementierung von R data.table basiert fread.
Lesen Sie mehr unter https://github.com/h2oai/datatable Wenn Sie das Pandas-Objekt laden möchten, können Sie es einfach ausführen

pandas_dataframe = dt.fread(srcfile).to_pandas()

Ich würde vorschlagen, die offizielle Dokumentation von Pandas zu IO im Auge zu behalten . Die Wahlmöglichkeiten ändern sich je nach Entwicklungszyklus und ständig kommen neue Formate hinzu. Sie veröffentlichen auch den Benchmark.

Es gibt ein neues Python-Paket für Data Mining mit dem Namen DaPy . Welches eine einfache E/A-API hat und schnell genug für Sie ist. Laut dem Leistungstest des Autors benötigte DaPy 12,5 Sekunden zum Laden einer CSV-Datei mit mehr als 2 Millionen Datensätzen, während Pandas 4 Sekunden brauchten. DaPy basiert jedoch auf einigen Python-nativen Datenstrukturen und ist einfacher zu verwenden.

cmd: pip install DaPy 
>>> import DaPy as dp
>>> data = dp.read('file.csv')
>>> data.show()