Ich habe eine DataFrame
von Pandas:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Ausgabe:
c1 c2
0 10 100
1 11 110
2 12 120
Jetzt möchte ich über die Zeilen dieses Rahmens iterieren. Für jede Zeile möchte ich über den Namen der Spalten auf ihre Elemente (Werte in Zellen) zugreifen können. Zum Beispiel:
for row in df.rows:
print row['c1'], row['c2']
Ist das bei Pandas möglich?
Ich habe diese ähnliche Frage gefunden . Aber es gibt mir nicht die Antwort, die ich brauche. Zum Beispiel wird dort empfohlen, Folgendes zu verwenden:
for date, row in df.T.iteritems():
oder
for row in df.iterrows():
Aber ich verstehe nicht, was das row
Objekt ist und wie ich damit arbeiten kann.
iter*
Funktionen sollten in sehr seltenen Fällen verwendet werden. Auch verwandt .iterrows
, es gibt bessere Möglichkeiten, über einen DataFrame zu iterieren. Sie können an diesem Punkt auch einfach über eine Liste von Listen iterieren. Wenn Sie an dem Punkt angelangt sind, an dem Sie nur noch über DataFrames iterieren, hat die Verwendung eines DataFrames überhaupt keinen Vorteil (vorausgesetzt, Sie iterieren nur darüber). Nur mein 2c.pandas
ist es die erste Wahl, eine CSV-Datei zu lesen, auch wenn der Datensatz klein ist. Es ist einfach einfacher zu programmieren, die Daten mit APIs zu manipulierenAntworten:
DataFrame.iterrows ist ein Generator, der sowohl Index als auch Zeile liefert
quelle
431341610650
wo gelesen wurden als4.31E+11
. Gibt es einen Weg, um die d-Typen zu erhalten?itertuples
, wie unten erklärt. Siehe auch pandas.pydata.org/pandas-docs/stable/generated/…Antwort: NICHT * !
Die Iteration bei Pandas ist ein Anti-Muster und sollte nur durchgeführt werden, wenn Sie alle anderen Optionen ausgeschöpft haben. Sie sollten keine Funktion mit "
iter
" im Namen für mehr als ein paar tausend Zeilen verwenden, da Sie sich sonst an viel Warten gewöhnen müssen .Möchten Sie einen DataFrame drucken? Verwenden Sie
DataFrame.to_string()
.Möchten Sie etwas berechnen? Suchen Sie in diesem Fall nach Methoden in dieser Reihenfolge (Liste von hier geändert ):
for
Schleife)DataFrame.apply()
: i) Reduktionen, die in Cython durchgeführt werden können, ii) Iteration im PythonraumDataFrame.itertuples()
unditeritems()
DataFrame.iterrows()
iterrows
unditertuples
(beide erhalten viele Stimmen bei der Beantwortung dieser Frage) sollten in sehr seltenen Fällen verwendet werden, z. B. zum Generieren von Zeilenobjekten / Namensetupeln für die sequentielle Verarbeitung, was wirklich das einzige ist, wofür diese Funktionen nützlich sind.Appell an die Behörde
Auf der Dokumentseite zur Iteration befindet sich ein großes rotes Warnfeld mit der Aufschrift:
* Es ist eigentlich etwas komplizierter als "nicht".
df.iterrows()
ist die richtige Antwort auf diese Frage, aber "vectorize your ops" ist die bessere. Ich werde zugeben, dass es Umstände gibt, unter denen eine Iteration nicht vermieden werden kann (zum Beispiel einige Operationen, bei denen das Ergebnis von dem für die vorherige Zeile berechneten Wert abhängt). Es bedarf jedoch einiger Vertrautheit mit der Bibliothek, um zu wissen, wann. Wenn Sie nicht sicher sind, ob Sie eine iterative Lösung benötigen, tun Sie dies wahrscheinlich nicht. PS: Um mehr über meine Gründe für das Schreiben dieser Antwort zu erfahren, gehen Sie ganz nach unten.Schneller als Looping: Vektorisierung , Cython
Eine gute Anzahl grundlegender Operationen und Berechnungen wird von Pandas "vektorisiert" (entweder über NumPy oder über zythonisierte Funktionen). Dies umfasst Arithmetik, Vergleiche, (die meisten) Reduzierungen, Umformen (z. B. Schwenken), Verknüpfungen und Groupby-Operationen. In der Dokumentation zu Essential Basic Functionality finden Sie eine geeignete vektorisierte Methode für Ihr Problem.
Wenn keine vorhanden ist, können Sie Ihre eigenen mit benutzerdefinierten Cython-Erweiterungen schreiben .
Next Best Thing: Listenverständnisse *
Listenverständnisse sollten Ihre nächste Anlaufstelle sein, wenn 1) keine vektorisierte Lösung verfügbar ist, 2) die Leistung wichtig, aber nicht wichtig genug ist, um den Aufwand für die Cythonisierung Ihres Codes zu bewältigen, und 3) Sie versuchen, eine elementweise Transformation durchzuführen auf Ihrem Code. Es gibt zahlreiche Hinweise darauf, dass das Listenverständnis für viele gängige Pandas-Aufgaben ausreichend schnell (und manchmal sogar schneller) ist.
Die Formel ist einfach,
Wenn Sie Ihre Geschäftslogik in eine Funktion einkapseln können, können Sie ein Listenverständnis verwenden, das sie aufruft. Durch die Einfachheit und Geschwindigkeit von Raw Python können Sie beliebig komplexe Dinge zum Laufen bringen.
Vorsichtsmaßnahmen Das
Verständnis der Liste setzt voraus, dass Ihre Daten einfach zu verarbeiten sind. Dies bedeutet, dass Ihre Datentypen konsistent sind und Sie keine NaNs haben. Dies kann jedoch nicht immer garantiert werden.
zip(df['A'], df['B'], ...)
anstattdf[['A', 'B']].to_numpy()
diese implizit auf den am häufigsten verwendeten Typ zu übertragen. Wenn beispielsweise A numerisch und B eine Zeichenfolge ist,to_numpy()
wird das gesamte Array in eine Zeichenfolge umgewandelt, was möglicherweise nicht Ihren Wünschen entspricht. Glücklicherweise ist daszip
Pingen Ihrer Spalten die einfachste Problemumgehung.* YMMV für die im genannten Gründen Caveats Abschnitt oben.
Ein offensichtliches Beispiel
Lassen Sie uns den Unterschied anhand eines einfachen Beispiels für das Hinzufügen von zwei Pandas-Spalten demonstrieren
A + B
. Dies ist eine vektorisierbare Operation, so dass es leicht ist, die Leistung der oben diskutierten Methoden gegenüberzustellen.Benchmarking-Code als Referenz.
Ich sollte jedoch erwähnen, dass es nicht immer so geschnitten und trocken ist. Manchmal lautet die Antwort auf "Was ist die beste Methode für eine Operation?" "Es hängt von Ihren Daten ab". Mein Rat ist, verschiedene Ansätze für Ihre Daten zu testen, bevor Sie sich für einen entscheiden.
Weiterführende Literatur
10 Minuten zu Pandas und grundlegende Funktionen - Nützliche Links, die Sie in Pandas und seine Bibliothek vektorisierter * / cythonisierter Funktionen einführen.
Verbessern der Leistung - Eine Einführung aus den Dokumenten zur Verbesserung der Standard-Pandas-Operationen
Sind For-Loops bei Pandas wirklich schlecht? Wann sollte es mich interessieren? - eine ausführliche Beschreibung von mir zum Listenverständnis und ihrer Eignung für verschiedene Operationen (hauptsächlich solche mit nicht numerischen Daten)
Wann sollte ich jemals pandas apply () in meinem Code verwenden wollen? -
apply
ist langsam (aber nicht so langsam wie dieiter*
Familie. Es gibt jedoch Situationen, in denen manapply
eine ernsthafte Alternative in Betracht ziehen kann (oder sollte) , insbesondere bei einigenGroupBy
Operationen).* Pandas-String-Methoden werden in dem Sinne "vektorisiert", dass sie in der Reihe angegeben sind, aber für jedes Element gelten. Die zugrunde liegenden Mechanismen sind immer noch iterativ, da Zeichenfolgenoperationen von Natur aus schwer zu vektorisieren sind.
Warum ich diese Antwort geschrieben habe
Ein häufiger Trend, den ich bei neuen Benutzern bemerke, besteht darin, Fragen an das Formular "Wie kann ich über meine df iterieren, um X auszuführen?" Zu stellen. Anzeigen von Code, der aufgerufen wird,
iterrows()
während etwas in einer for-Schleife ausgeführt wird. Hier ist warum. Ein neuer Benutzer in der Bibliothek, der nicht mit dem Konzept der Vektorisierung vertraut ist, wird sich wahrscheinlich den Code vorstellen, der sein Problem löst, indem er über seine Daten iteriert, um etwas zu tun. Da sie nicht wissen, wie sie über einen DataFrame iterieren sollen, googeln sie ihn zuerst und landen hier bei dieser Frage. Sie sehen dann die akzeptierte Antwort, die ihnen sagt, wie es geht, und sie schließen die Augen und führen diesen Code aus, ohne vorher zu fragen, ob Iteration nicht das Richtige ist.Ziel dieser Antwort ist es, neuen Benutzern zu vermitteln, dass Iteration nicht unbedingt die Lösung für jedes Problem ist und dass es bessere, schnellere und idiomatischere Lösungen geben kann und dass es sich lohnt, Zeit in ihre Erforschung zu investieren. Ich versuche nicht, einen Krieg zwischen Iteration und Vektorisierung zu beginnen, aber ich möchte, dass neue Benutzer informiert werden, wenn sie Lösungen für ihre Probleme mit dieser Bibliothek entwickeln.
quelle
zip(df['A'], df['B'])
statt zu schleifendf.iterrows()
.iterrows()
Iterationen spezifisch anzuprangern und sie implizit anzuprangern, wenn und wann bessere Alternativen existieren.for
Schleifen alleine sind in Ordnung, aber Listenverständnisse sind besser, wenn Sie iterativ elementweise Transformationen durchführen.DataFrame.values
Konvertiert jede Spalte in einen gemeinsamen Datentyp.DataFrame.to_numpy()
macht das auch. Glücklicherweise können wirzip
mit einer beliebigen Anzahl von Spalten verwenden.Überlegen Sie zunächst, ob Sie wirklich über Zeilen in einem DataFrame iterieren müssen. In dieser Antwort finden Sie Alternativen.
Wenn Sie immer noch über Zeilen iterieren müssen, können Sie die folgenden Methoden verwenden. Beachten Sie einige wichtige Vorsichtsmaßnahmen, die in keiner der anderen Antworten erwähnt werden.
DataFrame.iterrows ()
DataFrame.itertuples ()
itertuples()
soll schneller sein alsiterrows()
Beachten Sie jedoch laut den Dokumenten (Pandas 0.24.2 im Moment):
iterrows: stimmt
dtype
möglicherweise nicht von Zeile zu Zeile übereiniterrows: Ändern Sie keine Zeilen
Verwenden Sie stattdessen DataFrame.apply () :
itertuples:
Weitere Informationen finden Sie in den Pandas-Dokumenten zur Iteration .
quelle
for row in df[['c1','c2']].itertuples(index=True, name=None):
, dass nur bestimmte Spalten in den Zeileniterator aufgenommen werden sollen.getattr(row, "c1")
können Sie nur verwendenrow.c1
.getattr(row, "c1")
anstelle vonrow.c1
Leistungsvorteilen verlierenitertuples
und stattdessen iterrows verwenden sollten, wenn Sie tatsächlich über eine Zeichenfolge zur Eigenschaft gelangen müssen.numba
und zu verbesserncython
(dieselben Dokumente sagen, dass es sich immer lohnt, zuerst in Python zu optimieren). Ich habe diese Antwort geschrieben, um anderen zu helfen, (manchmal frustrierende) Probleme zu vermeiden, da keine der anderen Antworten diese Vorbehalte erwähnt. Jemanden irrezuführen oder zu sagen, "das ist das Richtige", war nie meine Absicht. Ich habe die Antwort verbessert.Sie sollten verwenden
df.iterrows()
. Das zeilenweise Durchlaufen ist jedoch nicht besonders effizient, daSeries
Objekte erstellt werden müssen.quelle
Dies
iterrows()
ist zwar eine gute Option,itertuples()
kann aber manchmal viel schneller sein:quelle
for a,b,c in izip(df["a"],df["b"],df["c"]:
ist fast gleich schnell.iterrows()
jede Datenzeile in eine Reihe ein, währenditertuples()
dies nicht der Fall ist.df
sie aus einem Wörterbuch erstellt wurde und sich daherrow[1]
auf eine der Spalten beziehen kann. Wie sich herausstellt, sind die Zeiten für die Ganzzahl im Vergleich zu den Float-Spalten ungefähr gleich.Sie können auch
df.apply()
Zeilen durchlaufen und auf mehrere Spalten für eine Funktion zugreifen.docs: DataFrame.apply ()
quelle
apply
nicht über Zeilen "iteriert" wird, sondern eine Funktion zeilenweise angewendet wird. Der obige Code würde nicht funktionieren , wenn Sie wirklich tun müssen Iterationen und Indizes, zum Beispiel , wenn die Werte in den verschiedenen Reihen zu vergleichen (in diesem Fall können Sie tun nichts anderes als Iterieren).Sie können die Funktion df.iloc wie folgt verwenden:
quelle
itertuples
Erhält Datentypen, entfernt jedoch alle Namen, die ihm nicht gefallen.iterrows
macht das Gegenteil.for i in range(df.shape[0])
dieser Ansatz möglicherweise etwas beschleunigt wird, ist er für meine Anwendung immer noch etwa 3,5-mal langsamer als der oben beschriebene iterrows () -Ansatz.my_iter = df.itertuples()
der Speicher doppelt so viel Speicherplatz benötigt und viel Zeit zum Kopieren benötigt wird. Gleiches gilt füriterrows()
.Ich suchte nach dem Iterieren von Zeilen UND Spalten und endete hier so:
quelle
Sie können Ihren eigenen Iterator schreiben, der implementiert
namedtuple
Dies ist direkt vergleichbar mit
pd.DataFrame.itertuples
. Ich möchte dieselbe Aufgabe effizienter ausführen.Für den angegebenen Datenrahmen mit meiner Funktion:
Oder mit
pd.DataFrame.itertuples
:Ein umfassender Test
Wir testen, ob alle Spalten verfügbar sind und die Spalten untergeordnet werden.
quelle
intertuples
, orange Linie ist eine Liste eines Iterators durch einen Ertragsblock.interrows
wird nicht verglichen.Wie kann ich effizient iterieren?
Wenn Sie einen Pandas-Datenrahmen wirklich iterieren müssen, sollten Sie wahrscheinlich die Verwendung von iterrows () vermeiden . Es gibt verschiedene Methoden und das Übliche
iterrows()
ist alles andere als das Beste. itertuples () kann 100-mal schneller sein.Zusamenfassend:
df.itertuples(name=None)
. Insbesondere, wenn Sie eine feste Anzahl von Spalten und weniger als 255 Spalten haben. Siehe Punkt (3)df.itertuples()
außer wenn Ihre Spalten Sonderzeichen wie Leerzeichen oder '-' enthalten. Siehe Punkt (2)itertuples()
auch im letzten Beispiel möglich, wenn Ihr Datenrahmen seltsame Spalten enthält. Siehe Punkt (4)iterrows()
wenn Sie die vorherigen Lösungen nicht können. Siehe Punkt (1)Verschiedene Methoden zum Durchlaufen von Zeilen in einem Pandas-Datenrahmen:
Generieren Sie einen zufälligen Datenrahmen mit einer Million Zeilen und 4 Spalten:
1) Das Übliche
iterrows()
ist praktisch, aber verdammt langsam:2) Die Standardeinstellung
itertuples()
ist bereits viel schneller, funktioniert jedoch nicht mit Spaltennamen wieMy Col-Name is very Strange
(Sie sollten diese Methode vermeiden, wenn Ihre Spalten wiederholt werden oder wenn ein Spaltenname nicht einfach in einen Python-Variablennamen konvertiert werden kann):3) Die Standardeinstellung
itertuples()
mit name = None ist noch schneller, aber nicht sehr praktisch, da Sie eine Variable pro Spalte definieren müssen.4) Schließlich ist der Name
itertuples()
langsamer als der vorherige Punkt, aber Sie müssen keine Variable pro Spalte definieren und es funktioniert mit Spaltennamen wieMy Col-Name is very Strange
.Ausgabe:
Dieser Artikel ist ein sehr interessanter Vergleich zwischen Iterrows und Itertuples
quelle
Um alle Zeilen in a zu schleifen
dataframe
, können Sie Folgendes verwenden:quelle
quelle
Manchmal ist ein nützliches Muster:
Was in ... resultiert:
quelle
Um alle Zeilen in a zu schleifen
dataframe
und die Werte jeder Zeile bequem zu verwenden ,namedtuples
kann inndarray
s konvertiert werden . Zum Beispiel:Durch die Zeilen iterieren:
Ergebnisse in:
Bitte beachten Sie, dass , wenn
index=True
, der Index als das erste Element des Tupels hinzugefügt wird , die für einige Anwendungen unerwünscht sein kann.quelle
Es gibt eine Möglichkeit, Wurfzeilen zu iterieren, während im Gegenzug ein DataFrame und keine Serie abgerufen wird. Ich sehe niemanden, der erwähnt, dass Sie den Index als Liste für die Zeile übergeben können, die als DataFrame zurückgegeben werden soll:
Beachten Sie die Verwendung von doppelten Klammern. Dies gibt einen DataFrame mit einer einzelnen Zeile zurück.
quelle
Zum Anzeigen und Ändern von Werten würde ich verwenden
iterrows()
. In einer for-Schleife und mithilfe des Tupel-Entpackens (siehe Beispiel :) verwendei, row
ich das,row
um nur den Wert anzuzeigen undi
mit derloc
Methode zu verwenden, wenn ich Werte ändern möchte. Wie in den vorherigen Antworten angegeben, sollten Sie hier nichts ändern, über das Sie iterieren.Hier ist das
row
in der Schleife eine Kopie dieser Zeile und keine Ansicht davon. Daher sollten Sie NICHT so etwas schreibenrow['A'] = 'New_Value'
, da dies den DataFrame nicht ändert. Sie können jedoch den DataFrame verwendeni
undloc
angeben, um die Arbeit auszuführen.quelle
Ich weiß, dass ich zu spät zur antwortenden Partei komme, aber ich wollte nur die obige Antwort von @ cs95 ergänzen, die meiner Meinung nach die akzeptierte Antwort sein sollte. In seiner Antwort zeigt er, dass die Vektorisierung von Pandas andere Pandas-Methoden zur Berechnung von Datenframes bei weitem übertrifft.
Ich wollte hinzufügen, dass wenn Sie den Datenrahmen zuerst in ein Numpy-Array konvertieren und dann die Vektorisierung verwenden, dieser sogar noch schneller ist als die Pandas-Datenrahmenvektorisierung (und dies schließt die Zeit ein, ihn wieder in eine Datenrahmenserie umzuwandeln).
Wenn Sie dem Benchmark-Code von @ cs95 die folgenden Funktionen hinzufügen, wird dies ziemlich deutlich:
quelle
Sie können auch eine
numpy
Indizierung durchführen, um die Geschwindigkeit noch weiter zu steigern. Es iteriert nicht wirklich, funktioniert aber für bestimmte Anwendungen viel besser als die Iteration.Möglicherweise möchten Sie es auch in ein Array umwandeln. Diese Indizes / Auswahlen sollten sich bereits wie Numpy-Arrays verhalten, aber ich bin auf Probleme gestoßen und musste sie umwandeln
quelle
Es gibt so viele Möglichkeiten, die Zeilen im Pandas-Datenrahmen zu durchlaufen. Ein sehr einfacher und intuitiver Weg ist:
quelle
In diesem Beispiel wird iloc verwendet, um jede Ziffer im Datenrahmen zu isolieren.
quelle
Einige Bibliotheken (z. B. eine von mir verwendete Java-Interop-Bibliothek) erfordern die gleichzeitige Übergabe von Werten, z. B. beim Streaming von Daten. Um die Streaming-Natur zu replizieren, "streame" ich meine Datenrahmenwerte nacheinander. Ich habe Folgendes geschrieben, was von Zeit zu Zeit nützlich ist.
Welches kann verwendet werden:
Und behält die Werte- / Namenszuordnung für die Zeilen bei, die iteriert werden. Offensichtlich ist es viel langsamer als die Verwendung von apply und Cython wie oben angegeben, ist aber unter bestimmten Umständen erforderlich.
quelle
Zusamenfassend
Details in diesem Video
Benchmark
quelle