Ich führe regelmäßig Pandas-Operationen an Datenrahmen mit mehr als 15 Millionen Zeilen durch und würde gerne Zugriff auf eine Fortschrittsanzeige für bestimmte Operationen haben.
Gibt es eine textbasierte Fortschrittsanzeige für Pandas Split-Apply-Combine-Operationen?
Zum Beispiel in so etwas wie:
df_users.groupby(['userID', 'requestDate']).apply(feature_rollup)
Dabei feature_rollup
handelt es sich um eine etwas komplizierte Funktion, die viele DF-Spalten verwendet und mithilfe verschiedener Methoden neue Benutzerspalten erstellt. Diese Vorgänge können bei großen Datenrahmen eine Weile dauern. Daher möchte ich wissen, ob eine textbasierte Ausgabe in einem iPython-Notizbuch möglich ist, das mich über den Fortschritt auf dem Laufenden hält.
Bisher habe ich kanonische Loop-Fortschrittsindikatoren für Python ausprobiert, aber sie interagieren nicht auf sinnvolle Weise mit Pandas.
Ich hoffe, dass ich in der Pandas-Bibliothek / -Dokumentation etwas übersehen habe, das es einem ermöglicht, den Fortschritt eines Split-Apply-Combine zu erkennen. Eine einfache Implementierung würde möglicherweise die Gesamtzahl der Datenrahmen-Teilmengen betrachten, an denen die apply
Funktion arbeitet, und den Fortschritt als den abgeschlossenen Bruchteil dieser Teilmengen melden.
Muss das vielleicht der Bibliothek hinzugefügt werden?
Antworten:
Aufgrund der großen Nachfrage
tqdm
hat Unterstützung für hinzugefügtpandas
. Im Gegensatz zu den anderen Antworten wird dies Pandas nicht merklich verlangsamen - hier ein Beispiel fürDataFrameGroupBy.progress_apply
:Wenn Sie daran interessiert sind, wie dies funktioniert (und wie Sie es für Ihre eigenen Rückrufe ändern können), lesen Sie die Beispiele zu github , die vollständige Dokumentation zu pypi oder importieren Sie das Modul und führen Sie es aus
help(tqdm)
.BEARBEITEN
Um die ursprüngliche Frage direkt zu beantworten, ersetzen Sie:
mit:
Hinweis: tqdm <= v4.8 : Für Versionen von tqdm unter 4.8 mussten Sie stattdessen Folgendes
tqdm.pandas()
tun:quelle
tqdm
wurde ursprünglich nur für einfache iterables erstellt:from tqdm import tqdm; for i in tqdm( range(int(1e8)) ): pass
Die Pandas-Unterstützung war ein kürzlich von mir durchgeführter Hack :)from tqdm import tqdm_notebook; tqdm_notebook().pandas(*args, **kwargs)
hier zu sehentqdm
v5, wodurch die Dinge modularer werden.Jeffs Antwort optimieren (und dies als wiederverwendbare Funktion haben).
Hinweis: Der Prozentsatz für die Aktualisierung des Fortschritts inline wird aktualisiert . Wenn Ihre Funktion nicht funktioniert, funktioniert dies nicht.
Wie üblich können Sie dies als Methode zu Ihren groupby-Objekten hinzufügen:
Wie in den Kommentaren erwähnt, ist dies keine Funktion, an deren Implementierung Kernpandas interessiert wären. Mit Python können Sie diese jedoch für viele Pandas-Objekte / -Methoden erstellen (dies wäre ein ziemlicher Arbeitsaufwand ... obwohl Sie diesen Ansatz verallgemeinern sollten).
quelle
Falls Sie Unterstützung für die Verwendung in einem Jupyter / ipython-Notizbuch benötigen, wie ich es getan habe, finden Sie hier eine hilfreiche Anleitung und Quelle für den entsprechenden Artikel :
Beachten Sie den Unterstrich in der Importanweisung für
_tqdm_notebook
. Wie in dem Artikel erwähnt, befindet sich die Entwicklung in der späten Beta-Phase.quelle
Für alle, die tqdm auf ihren benutzerdefinierten parallelen Pandas-Apply-Code anwenden möchten.
(Ich habe im Laufe der Jahre einige der Bibliotheken für die Parallelisierung ausprobiert, aber ich habe nie eine 100% ige Parallelisierungslösung gefunden, hauptsächlich für die Apply-Funktion, und ich musste immer zurückkommen, um meinen "manuellen" Code zu erhalten.)
df_multi_core - das ist das, was du anrufst . Es akzeptiert:
_df_split - Dies ist eine interne Hilfsfunktion , die global zum laufenden Modul positioniert werden muss (Pool.map ist "platzierungsabhängig"), andernfalls würde ich sie intern lokalisieren.
Hier ist der Code aus meinem Kern (ich werde dort weitere Pandas-Funktionstests hinzufügen):
Unten ist ein Testcode für eine parallelisierte Anwendung mit tqdm "progress_apply".
In der Ausgabe sehen Sie 1 Fortschrittsbalken für die Ausführung ohne Parallelisierung und Fortschrittsbalken pro Kern für die Ausführung mit Parallelisierung. Es gibt ein leichtes Hickup und manchmal erscheinen die restlichen Kerne sofort, aber selbst dann denke ich, dass es nützlich ist, da Sie die Fortschrittsstatistiken pro Kern erhalten (z. B. it / sec und Gesamtaufzeichnungen).
Vielen Dank an @abcdaa für diese großartige Bibliothek!
quelle
try: splits = np.array_split(df[subset], njobs) except ValueError: splits = np.array_split(df, njobs)
Wechseln Sie aufgrund der KeyError-Ausnahme anstelle von ValueError zu Exception, um alle Fälle zu behandeln.Sie können dies leicht mit einem Dekorateur tun
Verwenden Sie dann einfach die modifizierte_Funktion (und ändern Sie sie, wenn Sie möchten, dass sie gedruckt wird).
quelle
logged_apply(g, func)
Funktion zu packen, in der Sie Zugriff auf die Bestellung haben und von Anfang an protokollieren können.Ich habe Jeffs Antwort dahingehend geändert , dass sie eine Summe enthält, sodass Sie den Fortschritt und eine Variable verfolgen können, um nur alle X-Iterationen zu drucken (dies verbessert die Leistung tatsächlich um ein Vielfaches, wenn "print_at" einigermaßen hoch ist).
Die Funktion clear_output () stammt von
Wenn nicht auf IPython, macht Andy Haydens Antwort das ohne
quelle