Warum wird die Verkettung von DataFrames exponentiell langsamer?

8

Ich habe eine Funktion, die einen DataFrame verarbeitet, hauptsächlich um Daten in Buckets zu verarbeiten. Erzeuge eine binäre Matrix von Features in einer bestimmten Spalte mit pd.get_dummies(df[col]) .

Um zu vermeiden, dass alle meine Daten mit dieser Funktion gleichzeitig verarbeitet werden (was den Speicher auslastet und iPython zum Absturz bringt), habe ich den großen Datenrahmen mit Hilfe von:

in Stücke zerlegt %Vor%

pd.get_dummies(df) erstellt automatisch neue Spalten basierend auf dem Inhalt von df[col] und diese unterscheiden sich wahrscheinlich für jede df in df_list .

Nach der Verarbeitung verknüpfe ich die DataFrames wieder mit:

%Vor%

Die Verarbeitungszeit des ersten Chunks ist durchaus akzeptabel, wächst jedoch pro Chunk! Dies hat nichts mit dem preprocess_data(df_chunk) zu tun, da es keinen Grund für eine Erhöhung gibt. Tritt dieser Zeitanstieg als Folge des Aufrufs von pd.concat() ?

auf?

Siehe Protokoll unten:

%Vor%

Gibt es einen Workaround, um dies zu beschleunigen? Ich habe 2900 Brocken zu verarbeiten, so dass jede Hilfe geschätzt wird!

Öffnen Sie weitere Vorschläge in Python!

    
jfive 08.04.2016, 00:34
quelle

2 Antworten

8

Rufen Sie niemals DataFrame.append oder pd.concat in einer for-Schleife auf. Es führt zu quadratischem Kopieren.

pd.concat gibt einen neuen Datenrahmen zurück. Der Raum muss für das Neue reserviert werden DataFrame und Daten von den alten DataFrames müssen in das neue kopiert werden Datenrahmen. Berücksichtigen Sie die Kopiermenge, die für diese Zeile in for-loop erforderlich ist (vorausgesetzt, dass x die Größe 1 hat):

%Vor%

1 + 2 + 3 + ... + N = N(N-1)/2 . Es sind also O(N**2) Kopien erforderlich vervollständige die Schleife.

Betrachten Sie nun

%Vor%

Das Anhängen an eine Liste ist eine Operation O(1) und erfordert kein Kopieren. Jetzt Es gibt einen einzigen Aufruf von pd.concat , nachdem die Schleife beendet ist. Dieser Anruf an pd.concat benötigt N Kopien, da super_x N enthält DataFrames der Größe 1. Also, wenn auf diese Weise konstruiert, erfordert super_x O(N) Kopien.

    
unutbu 08.04.2016, 00:53
quelle
4

Jedes Mal, wenn Sie verketten, geben Sie eine Kopie der Daten zurück.

Sie möchten eine Liste Ihrer Stücke behalten und dann alles als letzten Schritt verketten.

%Vor%     
Alexander 08.04.2016 00:53
quelle