Frage Wie man über Zeilen in einem DataFrame in Pandas iteriert?


Ich habe einen DataFrames 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 des obigen Rahmens iterieren. Ich möchte für jede Zeile auf ihre Elemente (Werte in Zellen) mit dem Namen der Spalten zugreifen können. Ich möchte zum Beispiel so etwas haben:

for row in df.rows:
   print row['c1'], row['c2']

Ist es möglich, das in Pandas zu tun?

ich fand ähnliche Frage. Aber es gibt mir nicht die Antwort, die ich brauche. Zum Beispiel wird vorgeschlagen, dort zu verwenden:

for date, row in df.T.iteritems():

oder

for row in df.iterrows():

Aber ich verstehe nicht was row Objekt ist und wie ich damit arbeiten kann.


758
2018-05-10 07:04


Ursprung


Antworten:


Iterröschen ist ein Generator, der sowohl Index als auch Zeile liefert

In [18]: for index, row in df.iterrows():
   ....:     print row['c1'], row['c2']
   ....:     
10 100
11 110
12 120

1092
2018-05-10 07:07



Um die Zeile von DataFrame in Pandas zu durchlaufen, kann man verwenden:

itertuples() soll schneller sein als iterrows()

Aber sei vorsichtig, nach den Dokumenten (Pandas 0.21.1 im Moment):

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

    Weil Iterrows für jede Zeile eine Reihe zurückgibt, nicht erhalten dtypes über die Zeilen hinweg (dtypes werden in Spalten für DataFrames beibehalten).

  • Iterrows: Ändern Sie keine Zeilen

    Du solltest niemals modifizieren etwas, über das du iterierst. Dies funktioniert nicht garantiert in allen Fällen. Abhängig von den Datentypen gibt der Iterator eine Kopie und keine Ansicht zurück, und das Schreiben darauf hat keine Auswirkungen.

    Benutzen DataFrame.apply () stattdessen:

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

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


140
2017-12-07 16:41



Während iterrows() ist manchmal eine gute Wahl itertuples() kann 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

115
2017-09-20 13:52



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

Dokumentation: 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)

61
2018-06-01 06:24



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']

42
2017-09-07 12:56



Benutzen iertuples (). Es ist schneller als iterrows ():

for row in df.itertuples():
    print "c1 :",row.c1,"c2 :",row.c2

13
2017-07-27 16:32



ich suchte Wie man in Zeilen UND Spalten iteriert und hier endet so:

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

11
2018-01-17 09:41



Um alle Zeilen in a dataframe Sie können verwenden:

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]

10
2018-03-11 22:44



Sie können einen eigenen Iterator schreiben, der implementiert namedtuple

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 ziele darauf ab, die gleiche Aufgabe mit mehr Effizienz zu erfüllen.


Für den gegebenen 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 die Spalten untergliedert 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


10
2017-11-07 04:15



IMHO, die einfachste Entscheidung

 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]

6
2017-11-02 10:33