2017-07-07 1 views
1

Ich habe ein DataFrame df mit 541 Spalten, und ich muss alle eindeutigen Paare seiner Spaltennamen in den Zeilen eines separaten DataFrame speichern, jeweils 8 mal wiederholt.Wie erreiche ich am schnellsten einen Pandas DataFrame?

Ich dachte, ich würde eine leere DataFrame fp, Doppelschleife durch df Spaltennamen erstellen, in jede 8. Zeile einfügen, und füllen Sie die Lücken mit dem letzten verfügbaren Wert.

Als ich versuchte, dies zu tun, war ich verwirrt, wie lange es dauert. Mit 541 Spalten muss ich nur 146.611 mal schreiben, dauert aber deutlich über 20 Minuten. Dies scheint für nur Datenzugriff ungeheuerlich zu sein. Wo ist das Problem und wie kann ich es lösen? Es dauert weniger Zeit als für Pandas, eine Korrelationsmatrix mit den Spalten zu erzeugen, also muss ich etwas falsch machen.

Hier ist ein reproduzierbares Beispiel dafür, was ich meine:

fp = np.empty(shape = (146611, 10)) 
fp.fill(np.nan) 

fp = pd.DataFrame(fp) 

%timeit for idx in range(0, len(fp)): fp.iloc[idx, 0] = idx 

# 1 loop, best of 3: 22.3 s per loop 

Antwort

6

nicht ILoc/loc/gekettet-Indizierung tun. Allein die Verwendung der NumPy-Schnittstelle erhöht die Geschwindigkeit um ~ 180x. Wenn Sie den Elementzugriff weiter entfernen, können wir dies auf 180.000x erhöhen.

fp = np.empty(shape = (146611, 10)) 
fp.fill(np.nan) 

fp = pd.DataFrame(fp) 

# this confirms how slow data access is on my computer 
%timeit for idx in range(0, len(fp)): fp.iloc[idx, 0] = idx 

1 loops, best of 3: 3min 9s per loop 

# this accesses the underlying NumPy array, so you can directly set the data 
%timeit for idx in range(0, len(fp)): fp.values[idx, 0] = idx 

1 loops, best of 3: 1.19 s per loop 

Dies liegt daran, es umfangreicher Code ist, der für diese fancing Indizierung in der Python-Schicht geht unter ~ 10 us pro Schleife. Die Pandas-Indexierung sollte verwendet werden, um ganze Teilmengen von Daten abzurufen, die Sie dann für vektorisierte Operationen auf dem gesamten Datenrahmen verwenden. Der Zugriff auf einzelne Elemente ist glazial: Mit Python-Wörterbüchern können Sie die Leistung um das> 180fache steigern.

Die Dinge werden viel besser, wenn Sie auf Spalten oder Zeilen statt auf einzelne Elemente zugreifen: 3 Größenordnungen besser.

# set all items in 1 go. 
%timeit fp[0] = np.arange(146611) 
1000 loops, best of 3: 814 µs per loop 

Moral

Versuchen Sie nicht, einzelne Elemente über verkettete Indizierung zuzugreifen, loc oder iloc. Generieren Sie ein NumPy-Array in einer einzigen Zuordnung aus einer Python-Liste (oder einer C-Schnittstelle, wenn die Leistung absolut kritisch ist), und führen Sie dann Operationen für ganze Spalten oder Datenrahmen aus.

Mit NumPy-Arrays und Operationen direkt auf Spalten statt einzelne Elemente, haben wir eine satte 180.000+ Steigerung der Leistung. Nicht zu schäbig.

Verwandte Themen