it-swarm.dev

Aktualisieren Sie einen Datenrahmen in Pandas, während Sie Zeile für Zeile durchlaufen

Ich habe einen Pandas-Datenrahmen, der so aussieht (er ist ziemlich groß)

           date      exer exp     ifor         mat  
1092  2014-03-17  American   M  528.205  2014-04-19 
1093  2014-03-17  American   M  528.205  2014-04-19 
1094  2014-03-17  American   M  528.205  2014-04-19 
1095  2014-03-17  American   M  528.205  2014-04-19    
1096  2014-03-17  American   M  528.205  2014-05-17 

jetzt möchte ich Zeile für Zeile iterieren, und wenn ich jede Zeile durchgehe, kann sich der Wert von iforin jeder Zeile abhängig von einigen Bedingungen ändern.

Nun, wie aktualisiere ich das, während ich iteriere .. Ich habe ein paar Dinge ausprobiert, von denen keines funktioniert hat.

for i, row in df.iterrows():
    if <something>:
        row['ifor'] = x
    else:
        row['ifor'] = y

    df.ix[i]['ifor'] = x

Keiner dieser Ansätze scheint zu funktionieren. Die Werte werden im Datenrahmen nicht aktualisiert.

121
AMM

Sie können Werte in der Schleife mit df.set_value zuweisen:

for i, row in df.iterrows():
  ifor_val = something
  if <condition>:
    ifor_val = something_else
  df.set_value(i,'ifor',ifor_val)

wenn Sie die Zeilenwerte nicht benötigen, können Sie einfach die Indizes von df durchlaufen, aber ich habe die ursprüngliche for-Schleife beibehalten, falls Sie den Zeilenwert für etwas benötigen, das hier nicht angezeigt wird. 

Update

df.set_value () ist seit Version 0.21.0 veraltet. Sie können stattdessen df.at () verwenden:

  for i, row in df.iterrows():
      ifor_val = something
      if <condition>:
        ifor_val = something_else
      df.at[i,'ifor'] = ifor_val
124
rakke

Das Pandas DataFrame-Objekt sollte als Serie von Serien betrachtet werden. Mit anderen Worten, Sie sollten es in Form von Spalten betrachten. Der Grund, warum dies wichtig ist, liegt darin, dass Sie, wenn Sie pd.DataFrame.iterrows verwenden, Reihen als Reihen durchlaufen. Dies sind jedoch nicht der Serie, die der Datenrahmen speichert, und somit handelt es sich um neue Serien, die für Sie erstellt werden, während Sie iterieren. Dies bedeutet, dass diese Änderungen nicht im ursprünglichen Datenrahmen wiedergegeben werden, wenn Sie versuchen, sie zuzuweisen.

Ok, das ist jetzt aus dem Weg: Was machen wir?

Vorschläge vor diesem Beitrag beinhalten:

  1. pd.DataFrame.set_value ist veraltet ab Pandas Version 0.21
  2. pd.DataFrame.ix ist veraltet
  3. pd.DataFrame.loc ist in Ordnung, aber kann mit Array-Indexern arbeiten und Sie können es besser machen

Meine Empfehlung
Benutze pd.DataFrame.at

for i in df.index:
    if <something>:
        df.at[i, 'ifor'] = x
    else:
        df.at[i, 'ifor'] = y

Sie können dies sogar ändern in:

for i in df.index:
    df.at[i, 'ifor'] = x if <something> else y

Antwort auf Kommentar

und was ist, wenn ich den Wert der vorherigen Zeile für die if-Bedingung verwenden muss? 

for i in range(1, len(df) + 1):
    j = df.columns.get_loc('ifor')
    if <something>:
        df.iat[i - 1, j] = x
    else:
        df.iat[i - 1, j] = y
38
piRSquared

Sie sollten einen Wert durch df.ix[i, 'exp']=X oder df.loc[i, 'exp']=X anstelle von df.ix[i]['ifor'] = x zuweisen. 

Ansonsten arbeiten Sie an einer Ansicht und sollten eine Erwärmung bekommen:

-c:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead

Aber sicherlich sollte die Schleife wahrscheinlich durch einen vektorisierten Algorithmus ersetzt werden, um DataFrame vollständig zu nutzen, wie von @Phillip Cloud vorgeschlagen.

17
CT Zhu

Eine Methode, die Sie verwenden können, ist itertuples() . Sie führt DataFrame-Zeilen als Nameduples durch, wobei der Indexwert als erstes Element des Tupels gilt. Und es ist viel schneller im Vergleich zu iterrows(). Bei itertuples() enthält jede row ihre Index im DataFrame, und Sie können loc verwenden, um den Wert festzulegen. 

for row in df.itertuples():
    if <something>:
        df.at[row.Index, 'ifor'] = x
    else:
        df.at[row.Index, 'ifor'] = x

    df.loc[row.Index, 'ifor'] = x

Danke @SantiStSupery, mit .at ist viel schneller .

16
GoingMyWay

Nun, wenn Sie trotzdem iterieren wollen, warum nicht die einfachste Methode von allen verwenden, df['Column'].values[i]

df['Column'] = ''

for i in range(len(df)):
    df['Column'].values[i] = something/update/new_value

Oder wenn Sie die neuen Werte mit alten oder ähnlichen Werten vergleichen möchten, warum speichern Sie sie nicht in einer Liste und fügen Sie sie am Ende an.

mylist, df['Column'] = [], ''

for <condition>:
    mylist.append(something/update/new_value)

df['Column'] = mylist
6
Pranzell
for i, row in df.iterrows():
    if <something>:
        df.at[i, 'ifor'] = x
    else:
        df.at[i, 'ifor'] = y
5
Duane

Erhöhen Sie die MAX-Nummer aus einer Spalte. Zum Beispiel :

df1 = [sort_ID, Column1,Column2]
print(df1)

Meine Ausgabe:

Sort_ID Column1 Column2
12         a    e
45         b    f
65         c    g
78         d    h

MAX = df1['Sort_ID'].max() #This returns my Max Number 

Jetzt muss ich eine Spalte in df2 erstellen und die Spaltenwerte füllen, die den MAX erhöhen.

Sort_ID Column1 Column2
79      a1       e1
80      b1       f1
81      c1       g1
82      d1       h1

Hinweis: df2 enthält zunächst nur die Spalten1 und 2. Wir müssen die Sortid-Spalte erstellen und den MAX von df1 inkrementieren. 

0
Shazir Jabbar