Im Moment importiere ich jedes Mal, wenn ich das Skript ausführe, ein recht großes CSV
als DataFrame. Gibt es eine gute Lösung, um das DataFrame dauerhaft zwischen den Durchläufen verfügbar zu halten, damit ich nicht die ganze Zeit damit verbringen muss, auf das Skript zu warten?
Antworten
Zu viele Anzeigen?Wie bereits erwähnt, gibt es verschiedene Optionen und Dateiformate (HDF5, JSON, CSV, parquet, SQL), um ein Datenrahmen zu speichern. Allerdings ist pickle
(abhängig von Ihrer Konfiguration) kein Klassenbürger, weil:
pickle
ist ein potenzielles Sicherheitsrisiko. Form die Python-Dokumentation für Pickle:
Warnung Das
pickle
-Modul ist nicht sicher gegen fehlerhafte oder bösartig konstruierte Daten. Niemals Daten aus einer unvertrauenswürdigen oder nicht authentifizierten Quelle entpickeln.
-
pickle
ist langsam. Hier finden Sie hier und hier Benchmarks. -
pickle
ist nur für Python. Sie können die Ergebnisse nicht einfach mit anderen Tools oder Programmiersprachen lesen.
Je nach Ihrer Konfiguration/Nutzung gelten beide Einschränkungen nicht, aber ich würde pickle
nicht als Standardpersistenz für Pandas-Datenrahmen empfehlen.
Pandas DataFrames haben die Funktion to_pickle
, die nützlich ist, um ein DataFrame zu speichern:
import pandas as pd
a = pd.DataFrame({'A':[0,1,0,1,0],'B':[True, True, False, False, False]})
print a
# A B
# 0 0 True
# 1 1 True
# 2 0 False
# 3 1 False
# 4 0 False
a.to_pickle('my_file.pkl')
b = pd.read_pickle('my_file.pkl')
print b
# A B
# 0 0 True
# 1 1 True
# 2 0 False
# 3 1 False
# 4 0 False
Numpy-Dateiformate sind ziemlich schnell für numerische Daten
Ich verwende lieber numpy-Dateien, da sie schnell und einfach zu handhaben sind. Hier ist ein einfacher Benchmark zum Speichern und Laden eines Datenrahmens mit 1 Spalte mit 1 Million Punkten.
import numpy as np
import pandas as pd
num_dict = {'Spannung': np.random.rand(1000000)}
num_df = pd.DataFrame(num_dict)
unter Verwendung der ipython-%%timeit
-Zauberfunktion
%%timeit
with open('num.npy', 'wb') as np_file:
np.save(np_file, num_df)
das Ergebnis ist
100 Schleifen, bester von 3: 5,97 ms pro Schleife
um die Daten wieder in einen Datenrahmen zu laden
%%timeit
with open('num.npy', 'rb') as np_file:
data = np.load(np_file)
data_df = pd.DataFrame(data)
das Ergebnis ist
100 Schleifen, bester von 3: 5,12 ms pro Schleife
NICHT SCHLECHT!
NACHTEILE
Es gibt ein Problem, wenn Sie die numpy-Datei mit Python 2 speichern und dann versuchen, sie mit Python 3 zu öffnen (oder umgekehrt).
Ein weiterer recht frischer Test mit to_pickle()
.
Ich habe insgesamt 25 .csv
Dateien zu verarbeiten und das endgültige Dataframe
besteht aus ungefähr 2M Elementen.
(Hinweis: Neben dem Laden der .csv-Dateien manipuliere ich auch einige Daten und erweitere das Dataframe um neue Spalten.)
Das Durchgehen aller 25 .csv
Dateien und das Erstellen des Dataframes dauert ungefähr 14 Sekunden
.
Das Laden des gesamten Dataframes aus einer pkl
Datei dauert weniger als 1 Sekunde
https://docs.python.org/3/library/pickle.html
Die Pickle-Protokollformate:
Protokollversion 0 ist das originale "menschlich lesbare" Protokoll und ist abwärtskompatibel mit früheren Versionen von Python.
Protokollversion 1 ist ein altes binäres Format, das auch mit früheren Versionen von Python kompatibel ist.
Protokollversion 2 wurde in Python 2.3 eingeführt. Es ermöglicht effizienteres Pickling von neuen Klassen. Siehe PEP 307 für Informationen zu den Verbesserungen, die durch Protokoll 2 gebracht werden.
Protokollversion 3 wurde in Python 3.0 hinzugefügt. Es bietet explizite Unterstützung für Bytes-Objekte und kann nicht von Python 2.x unpickelt werden. Dies ist das Standardprotokoll und das empfohlene Protokoll, wenn Kompatibilität mit anderen Python 3-Versionen erforderlich ist.
Protokollversion 4 wurde in Python 3.4 hinzugefügt. Es fügt Unterstützung für sehr große Objekte, Pickling verschiedener Objekte und einige Datenformatoptimierungen hinzu. Siehe PEP 3154 für Informationen zu den Verbesserungen, die durch Protokoll 4 gebracht werden.