Tut pandas iterrows haben performance Probleme?
Habe ich bemerkt, eine sehr schlechte Leistung bei Verwendung von iterrows von pandas.
Ist das etwas, was von anderen erfahren? Ist es spezifisch für iterrows und sollte diese Funktion erspart werden, Daten von einer bestimmten Größe (ich arbeite mit 2-3 Millionen Zeilen)?
Diese Diskussion auf GitHub führte mich zu glauben, es wird verursacht, wenn das mischen dtypes in der dataframe, jedoch das einfache Beispiel unten zeigt, ist es auch bei Verwendung eines dtype (float64). Dies dauert 36 Sekunden auf meiner Maschine:
import pandas as pd
import numpy as np
import time
s1 = np.random.randn(2000000)
s2 = np.random.randn(2000000)
dfa = pd.DataFrame({'s1': s1, 's2': s2})
start = time.time()
i=0
for rowindex, row in dfa.iterrows():
i+=1
end = time.time()
print end - start
Warum sind vektorisierte Operationen wie bewerben so viel schneller? Ich vorstellen, es müssen einige Zeilen-iteration geht es auch.
Ich kann nicht herausfinden, wie man nicht verwenden, iterrows in meinem Fall (das werde ich sparen für eine Zukunft in Frage). Von daher würde ich schätzen, hören, wenn Sie konsequent in der Lage zu vermeiden, diese iteration. Ich mache Berechnungen basieren auf den Daten, die in separaten dataframes. Danke!
---Edit: eine vereinfachte version von dem, was ich ausführen will, wurde Hinzugefügt, unten---
import pandas as pd
import numpy as np
#%% Create the original tables
t1 = {'letter':['a','b'],
'number1':[50,-10]}
t2 = {'letter':['a','a','b','b'],
'number2':[0.2,0.5,0.1,0.4]}
table1 = pd.DataFrame(t1)
table2 = pd.DataFrame(t2)
#%% Create the body of the new table
table3 = pd.DataFrame(np.nan, columns=['letter','number2'], index=[0])
#%% Iterate through filtering relevant data, optimizing, returning info
for row_index, row in table1.iterrows():
t2info = table2[table2.letter == row['letter']].reset_index()
table3.ix[row_index,] = optimize(t2info,row['number1'])
#%% Define optimization
def optimize(t2info, t1info):
calculation = []
for index, r in t2info.iterrows():
calculation.append(r['number2']*t1info)
maxrow = calculation.index(max(calculation))
return t2info.ix[maxrow]
apply
ist NICHT vektorisiert.iterrows
ist umso schlimmer, als es Boxen alles (dass' das perf diff mitapply
). Sie sollten nur verwendet werdeniterrows
in sehr sehr wenigen Situationen. IMHO nie. Zeigen Sie, was Sie tatsächlich tun, mititerrows
.- Das Problem, das Sie verknüpft, anstatt zu tun hat mit den Boxen von einem
DatetimeIndex
inTimestamps
(implementiert in python-Platz), und dies wurde viel verbessert im master. - Siehe dieses Thema für eine Diskussion: github.com/pydata/pandas/issues/7194.
- Link zu der betreffenden Frage (diese bleiben allgemein): stackoverflow.com/questions/24875096/...
- Bitte empfehlen nicht die Verwendung von iterrows(). Es ist eine himmelschreiende enabler der schlimmsten anti-pattern in der Geschichte der pandas.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Generell
iterrows
sollte nur in sehr sehr speziellen Fällen. Dies ist die Allgemeine Rangfolge für die Ausführung verschiedener Operationen:Mithilfe einer benutzerdefinierten cython-routine ist in der Regel zu kompliziert, so lassen Sie uns das für einen Moment überspringen.
1) Vektorisierung ist IMMER die erste und beste Wahl. Allerdings gibt es einen kleinen Satz von Fällen, die nicht vektorisiert in offensichtlicher Weise (meist mit einer Wiederholung). Weiter, auf einem eher kleinen Rahmen, kann es schneller sein, zu anderen Methoden.
3) Gelten beinhaltet kann normalerweise getan werden, indem ein iterator ist in Cython Raum (dies geschieht intern in pandas) (dies ist ein) Fall.
Dies ist davon abhängig, was Los ist in den Ausdruck gelten. z.B.
df.apply(lambda x: np.sum(x))
ausgeführt werden, ziemlich schnell (natürlichdf.sum(1)
ist sogar besser). Aber so etwas wie:df.apply(lambda x: x['b'] + 1)
ausgeführt werden, die in python-Platz, und ist somit langsamer.4)
itertuples
nicht die box die Daten in eine Reihe, nur gibt es da ein Tupel5)
iterrows
TUT-box die Daten in einer Reihe. Es sei denn, Sie wirklich brauchen, verwenden Sie eine andere Methode.6) die Aktualisierung eines leeren frame-single-row-at-a-time. Ich habe gesehen, wie diese Methode verwendet viel zu viel. Es ist mit Abstand das langsamste. Es ist wohl Häufig (und Recht schnell für einige python-Strukturen), aber ein DataFrame hat eine ganze Reihe von Prüfungen auf die Indizierung, damit diese immer sehr langsam zu aktualisieren, eine Zeile zu einem Zeitpunkt. Viel besser, neue Strukturen und
concat
.itertuples
ist schneller alsapply
🙁pd.DataFrame.apply
ist oft langsamer alsitertuples
. Darüber hinaus ist es eine überlegung Wert Liste Verstehens,map
, die schlecht benanntnp.vectorize
undnumba
(in keiner bestimmten Reihenfolge) für nicht-vectorisable Berechnungen, siehe z.B. die Antwort.Vektor-Operationen in Numpy und pandas sind viel schneller als Skalare Operationen in Vanille-Python gibt es mehrere Gründe:
Fortgeführten Typ lookup: Python ist eine dynamisch typisierte Sprache, so gibt es Laufzeit-overhead für jedes element in einem array. Jedoch, Numpy (und damit pandas) durchführen von Berechnungen in C (oft über Cython). Der Typ des array ist bestimmt nur am Anfang der iteration ist; diese Einsparungen allein ist einer der größten Siege.
Besser Zwischenspeichern: Iteration über ein C-array ist cache-freundlich und deshalb sehr schnell. Ein pandas DataFrame ist eine "spaltenorientierte Tabelle", was bedeutet, dass jede Spalte ist eigentlich nur ein array. Also die native Aktionen, die Sie durchführen können auf einen DataFrame (wie addieren aller Elemente in einer Spalte) haben nur wenige cache-misses.
Mehr Möglichkeiten für Parallelität: Ein einfaches C-array betrieben werden kann mittels SIMD-Anweisungen. Einige Teile von Numpy ermöglichen, SIMD, je nach CPU und installation. Die Vorteile für die Parallelität nicht so dramatisch, wie die statische Typisierung und besser Zwischenspeichern, aber Sie sind immer noch eine solide gewinnen.
Moral von der Geschichte: das Vektor-Operationen in Numpy und pandas. Sie sind schneller als Skalare Operationen in Python-aus dem einfachen Grund, dass diese Vorgänge sind genau das, was ein C-Programmierer geschrieben hätte ohnehin von hand. (Außer, dass der array-Begriff ist viel einfacher zu Lesen als eine explizite Schleifen mit embedded-SIMD-Anweisungen.)
Hier ist der Weg zum tun ist das Ihr problem. Das ist alles vektorisiert.
Andere Möglichkeit ist die Verwendung
to_records()
, die schneller ist als beideitertuples
unditerrows
.Aber für deinen Fall gibt es viel Raum für andere Arten von Verbesserungen.
Hier mein final optimierte version
Benchmark-test:
Vollständige code:
Die final version ist fast 10x schneller als der ursprüngliche code. Die Strategie ist:
groupby
zu vermeiden, wiederholt den Vergleich von Werten.to_records
Zugriff auf raw-numpy.Datensätze Objekte.Ja, Pandas itertuples() ist schneller als iterrows().
Sie können finden Sie in der Dokumentation: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iterrows.html
"Zu bewahren dtypes während der Iteration über die Zeilen, es ist besser, itertuples (), die zurückgibt, namedtuples der Werte, und ist in der Regel schneller als iterrows."