wake-up-neo.com

Wie kann ich Zeilen in einem DataFrame in Pandas durchlaufen?

Ich habe ein 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 die Zeilen dieses Frames durchlaufen. Für jede Zeile möchte ich über den Namen der Spalten auf deren 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 fand das ähnliche Frage . Aber es gibt mir nicht die Antwort, die ich brauche. Beispielsweise 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 Objekt row ist und wie ich damit arbeiten kann.

1368
Roman

DataFrame.iterrows ist ein Generator, der sowohl Index als auch Zeile liefert

import pandas as pd
import numpy as np

df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])
for index, row in df.iterrows():
    print(row['c1'], row['c2'])

Output: 
   10 100
   11 110
   12 120
1916
waitingkuo

Überlegen Sie zunächst, ob Sie wirklich über Zeilen in einem DataFrame iterieren müssen . Siehe diese Antwort für 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.

itertuples() soll schneller sein als iterrows()

Beachten Sie jedoch laut Dokumentation (Pandas 0.24.2 im Moment):

  • iterrows: dtype stimmt möglicherweise nicht von Zeile zu Zeile überein

    Da iterrows für jede Zeile eine Reihe zurückgibt, werden keine D-Typen in den Zeilen beibehalten (D-Typen werden in den Spalten für DataFrames beibehalten). Um dtypes beim Durchlaufen der Zeilen beizubehalten, ist es besser, itertuples () zu verwenden, die namedtuples der Werte zurückgeben und die im Allgemeinen viel schneller sind als iterrows ().

  • iterrows: Ändern Sie keine Zeilen

    Sie sollten niemals etwas ändern , worüber Sie iterieren. Es ist nicht garantiert, dass dies in allen Fällen funktioniert. Abhängig von den Datentypen gibt der Iterator eine Kopie und keine Ansicht zurück, und das Schreiben darauf hat keine Auswirkung.

    Verwenden Sie stattdessen DataFrame.apply () :

    new_df = df.apply(lambda x: x * 2)
    
  • itertupel:

    Die Spaltennamen werden in Positionsnamen umbenannt, wenn sie ungültige Python Bezeichner sind, wiederholt werden oder mit einem Unterstrich beginnen. Bei einer großen Anzahl von Spalten (> 255) werden reguläre Tupel zurückgegeben.

Siehe Pandas-Dokumentation zur Iteration für weitere Einzelheiten.

295
viddik13

Sie sollten df.iterrows() verwenden. Die zeilenweise Iteration ist jedoch nicht besonders effizient, da Serienobjekte erstellt werden müssen.

186
Wes McKinney

Während iterrows() eine gute Option ist, kann itertuples() manchmal viel schneller sein:

df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})

%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop

%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop
142
e9t

Wie kann ich in Pandas über Zeilen in einem DataFrame iterieren?

Antwort: NICHT!

Die Iteration in pandas ist ein Anti-Pattern. Dies sollten Sie nur tun, wenn Sie alle anderen Möglichkeiten ausgeschöpft haben. Sie sollten keine Funktion mit "iter" im Namen für mehr als ein paar tausend Zeilen in Betracht ziehen, sonst müssen Sie sich an eine Menge des Wartens gewöhnen .

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 geändert von hier ):

  1. Vektorisierung
  2. Cython-Routinen
  3. List Comprehensions (Vanilla for Schleife)
  4. DataFrame.apply() : i) Reduzierungen, die in Cython durchgeführt werden können, ii) Iteration im Raum python
  5. DataFrame.itertuples() und iteritems()
  6. DataFrame.iterrows()

iterrows und itertuples (beide erhalten viele Stimmen bei der Beantwortung dieser Frage) sollten in sehr seltenen Fällen verwendet werden, z nützlich zum.

Appell an die Behörde
Die Dokumentseite bei Iteration hat ein riesiges rotes Warnfeld mit der Aufschrift:

Das Durchlaufen von pandas Objekten ist im Allgemeinen langsam. In vielen Fällen ist es nicht erforderlich, manuell über die Zeilen zu iterieren [...].


Schneller als Schleifen: Vektorisierung , Cython

Eine gute Anzahl grundlegender Operationen und Berechnungen werden von pandas "vektorisiert" (entweder durch NumPy oder durch cythonisierte Funktionen). Dies umfasst Arithmetik, Vergleiche, (die meisten) Verkleinerungen, Umformen (wie z. B. Schwenken), Verknüpfungen und Groupby-Operationen. Durchsuchen Sie die Dokumentation zu Essential Basic Functionality , um eine geeignete vektorisierte Methode für Ihr Problem zu finden.

Wenn es keine gibt, können Sie Ihre eigenen mit custom Cython-Erweiterungen schreiben.


Next Best Thing: List Comprehensions

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 ein eine gute Menge an Beweisen , um darauf hinzuweisen, dass das Listenverständnis für viele gängige pandas Aufgaben ausreichend schnell (und manchmal sogar schneller) ist.

Die Formel ist einfach,

# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `Zip`
result = [f(x, y) for x, y in Zip(df['col1'], df['col2'])]
# iterating over multiple columns
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]

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 Funktionieren bringen.


Ein offensichtliches Beispiel

Lassen Sie uns den Unterschied anhand eines einfachen Beispiels demonstrieren, bei dem zwei pandas Spalten A + B hinzugefügt werden. Dies ist eine vektorisierbare Operation, so dass es leicht ist, die Leistung der oben diskutierten Methoden gegenüberzustellen.

enter image description here

Referenzcode zu Ihrer Information

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.


Verweise

* Pandas Zeichenfolgenmethoden werden in dem Sinne "vektorisiert", dass sie in der Reihe angegeben sind, jedoch auf jedes Element angewendet werden. Die zugrunde liegenden Mechanismen sind immer noch iterativ, da Zeichenfolgenoperationen von Natur aus schwer zu vektorisieren sind.

123
cs95

Sie können auch df.apply() verwenden, um Zeilen zu durchlaufen und auf mehrere Spalten für eine Funktion zuzugreifen.

docs: DataFrame.apply ()

def valuation_formula(x, y):
    return x * y * 0.5

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)
79
cheekybastard

Sie können die Funktion df.iloc wie folgt verwenden:

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']
67
PJay

Ich suchte nach Wie man Zeilen UND Spalten durchläuft und endete hier so:

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)
27
Lucas B

Sie können Ihren eigenen Iterator schreiben, der namedtuple implementiert.

from collections import namedtuple

def myiter(d, cols=None):
    if cols is None:
        v = d.values.tolist()
        cols = d.columns.values.tolist()
    else:
        j = [d.columns.get_loc(c) for c in cols]
        v = d.values[:, j].tolist()

    n = namedtuple('MyTuple', cols)

    for line in iter(v):
        yield n(*line)

Dies ist direkt vergleichbar mit pd.DataFrame.itertuples. Ich möchte die gleiche Aufgabe effizienter erledigen.


Für den angegebenen Datenrahmen mit meiner Funktion:

list(myiter(df))

[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]

Oder mit pd.DataFrame.itertuples:

list(df.itertuples(index=False))

[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]

Ein umfassender Test
Wir testen, ob alle Spalten verfügbar sind und ob die Spalten untergeordnet sind.

def iterfullA(d):
    return list(myiter(d))

def iterfullB(d):
    return list(d.itertuples(index=False))

def itersubA(d):
    return list(myiter(d, ['col3', 'col4', 'col5', 'col6', 'col7']))

def itersubB(d):
    return list(d[['col3', 'col4', 'col5', 'col6', 'col7']].itertuples(index=False))

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns='iterfullA iterfullB itersubA itersubB'.split(),
    dtype=float
)

for i in res.index:
    d = pd.DataFrame(np.random.randint(10, size=(i, 10))).add_prefix('col')
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        res.at[i, j] = timeit(stmt, setp, number=100)

res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);

enter image description here

enter image description here

16
piRSquared

Um alle Zeilen in einem dataframe zu schleifen, können Sie Folgendes verwenden:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]
13
Pedro Lobito
 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]
13
Grag2015

Manchmal ist ein nützliches Muster:

# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
    print(row_dict)

Was in ... endet:

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}
7
Zach

Um alle Zeilen einer dataframe und verwenden Werte jeder Zeile bequemerweise zu durchlaufen, kann namedtuples in ndarrays konvertiert werden. Zum Beispiel:

df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])

Iterieren über die Zeilen:

for row in df.itertuples(index=False, name='Pandas'):
    print np.asarray(row)

ergebnisse in:

[ 1.   0.1]
[ 2.   0.2]

Beachten Sie, dass bei index=True, der Index wird als erstes Element des Tupels hinzugefügt, was für einige Anwendungen unerwünscht sein kann.

6
KutalmisB

Zum Anzeigen und Ändern von Werten würde ich iterrows() verwenden. In einer for-Schleife und unter Verwendung des Tupel-Entpackens (siehe Beispiel: i, row) verwende ich row, um nur den Wert anzuzeigen, und verwende i mit der loc -Methode, wenn Ich möchte Werte ändern. Wie in den vorherigen Antworten angegeben, sollten Sie hier nichts ändern, worüber Sie iterieren.

for i, row in df.iterrows():
    if row['A'] == 'Old_Value':
        df.loc[i,'A'] = 'New_value'  

Hier ist das row in der Schleife eine Kopie dieser Zeile und keine Ansicht davon. Daher sollten Sie NICHT so etwas wie row['A'] = 'New_Value' schreiben, da dies den DataFrame nicht verändert. Sie können jedoch i und loc verwenden und den DataFrame angeben, der die Arbeit erledigt.

2
HKRC

Sie können auch numpy indizieren, um eine noch höhere Geschwindigkeit zu erzielen. Es iteriert nicht wirklich, funktioniert aber für bestimmte Anwendungen viel besser als Iteration.

subset = row['c1'][0:5]
all = row['c1'][:]

Sie können es auch in ein Array umwandeln. Diese Indizes/Auswahlen sollen sich bereits wie Numpy-Arrays verhalten, aber ich bin auf Probleme gestoßen und musste sie besetzen

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file
1
James L.

Warum komplizieren die Dinge?

Einfach.

import pandas as pd
import numpy as np

# Here is an example dataframe
df_existing = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
for idx,row in df_existing.iterrows():
    print row['A'],row['B'],row['C'],row['D']
1

Es gibt so viele Möglichkeiten, die Zeilen in pandas Datenrahmen zu durchlaufen. Ein sehr einfacher und intuitiver Weg ist:

df=pd.DataFrame({'A':[1,2,3], 'B':[4,5,6],'C':[7,8,9]})
print(df)
for i in range(df.shape[0]):
    # For printing the second column
    print(df.iloc[i,1])
    # For printing more than one columns
    print(df.iloc[i,[0,2]])
1
shubham ranjan

In diesem Beispiel wird iloc verwendet, um jede Ziffer im Datenrahmen zu isolieren.

import pandas as pd

 a = [1, 2, 3, 4]
 b = [5, 6, 7, 8]

 mjr = pd.DataFrame({'a':a, 'b':b})

 size = mjr.shape

 for i in range(size[0]):
     for j in range(size[1]):
         print(mjr.iloc[i, j])
0
mjr2000