Actualice un dataframe en pandas mientras itera fila por fila

Tengo un dataframe de pandas que se parece a esto (es bastante grande)

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 

ahora me gustaría iterar fila por fila y al pasar por cada fila, el valor de ifor en cada fila puede cambiar dependiendo de algunas condiciones y necesito buscar otro dataframe.

Ahora, ¿cómo actualizo esto como itero? Probé algunas cosas que ninguna de ellas funcionó.

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

Ninguno de estos enfoques parece funcionar. No veo los valores actualizados en el dataframe.

Puede asignar valores en el bucle usando df.set_value:

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

Si no necesita los valores de fila, simplemente puede iterar sobre los índices de df, pero conservé el bucle for original en caso de que necesite el valor de fila para algo que no se muestra aquí.

actualizar

df.set_value () ha quedado en desuso desde la versión 0.21.0, puede usar df.at () en su lugar:

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

El objeto Pandas DataFrame debe considerarse como una serie de series. En otras palabras, debes pensar en términos de columnas. La razón por la que esto es importante es porque cuando usas pd.DataFrame.iterrows estás iterando a través de filas como Series. Pero estas no son las Series que el dataframe está almacenando, por lo que son nuevas Series que se crean para usted mientras itera. Eso implica que cuando intenta asignarles esas ediciones, esas ediciones no se reflejarán en el dataframe original.

Ok, ahora que está fuera del camino: ¿Qué hacemos?

Las sugerencias anteriores a esta publicación incluyen:

  1. pd.DataFrame.set_value está en desuso a partir de la versión 0.21 de Pandas
  2. pd.DataFrame.ix está en desuso
  3. pd.DataFrame.loc está bien, pero puede funcionar en indexadores de matriz y puede hacerlo mejor

Mi recomendación
Utilice pd.DataFrame.at

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

Incluso puedes cambiar esto a:

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

Respuesta a comentar

y ¿qué pasa si necesito usar el valor de la fila anterior para la condición if?

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

Un método que puede usar es itertuples() , itera sobre filas de DataFrame como se nombra timbres, con valor de índice como primer elemento de la tupla. Y es mucho más rápido en comparación con iterrows() . Para itertuples() , cada row contiene su Index en el dataframe, y puede usar loc para establecer el valor.

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

Gracias @SantiStSupery, usar .at es mucho más rápido .

Debe asignar un valor mediante df.ix[i, 'exp']=X o df.loc[i, 'exp']=X lugar de df.ix[i]['ifor'] = x .

De lo contrario, está trabajando en una vista y debería obtener un calentamiento:

-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

Pero ciertamente, el bucle probablemente debería ser reemplazado por algún algoritmo vectorizado para hacer un uso completo de DataFrame como sugirió @Phillip Cloud.

Bueno, si vas a iterar de todos modos, ¿por qué no usar el método más simple de todos, df['Column'].values[i]

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

O si desea comparar los valores nuevos con el anterior o algo así, ¿por qué no lo almacena en una lista y luego lo agrega al final?

 mylist, df['Column'] = [], '' for : mylist.append(something/update/new_value) df['Column'] = mylist 
 for i, row in df.iterrows(): if : df.at[i, 'ifor'] = x else: df.at[i, 'ifor'] = y 

Incrementa el número MAX de una columna. Por ejemplo :

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

Mi salida:

 Sort_ID Column1 Column2 12 ae 45 bf 65 cg 78 dh 

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

Ahora, necesito crear una columna en df2 y completar los valores de columna que incrementan el MAX.

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

Nota: inicialmente, df2 solo contendrá la Columna1 y la Columna2. Necesitamos que la columna Sortid sea creada e incremental del MAX desde df1.