python - recorrer - seleccionar columnas de un dataframe pandas
Actualice un marco de datos en pandas mientras itera fila por fila (6)
Bueno, si vas a iterar de todos modos, ¿por qué no utilizas 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 antiguos o algo así, ¿por qué no almacenarlo en una lista y luego agregarlo al final?
mylist, df[''Column''] = [], ''''
for <condition>:
mylist.append(something/update/new_value)
df[''Column''] = mylist
Tengo un marco de datos de pandas que se ve así (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 mientras reviso cada fila, el valor de ifor
en cada fila puede cambiar dependiendo de algunas condiciones y necesito buscar otro marco de datos.
Ahora, ¿cómo puedo actualizar esto mientras itero? Intenté algunas cosas, ninguna de ellas funcionó.
for i, row in df.iterrows():
if <something>:
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 marco de datos.
Debe asignar valor por 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 calentarse:
-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, loop probablemente debería ser reemplazado por algún algoritmo vectorizado para hacer un uso completo de DataFrame
como lo sugirió @Phillip Cloud.
El objeto Pandas DataFrame debería considerarse 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 utiliza pd.DataFrame.iterrows
está iterando a través de filas como Serie. Pero estas no son las Series que el marco de datos está almacenando, por lo que son Series nuevas que se crean para usted mientras itera. Eso implica que cuando intentes asignarlos, esas ediciones no se reflejarán en el marco de datos original.
Ok, ahora que eso está fuera del camino: ¿qué hacemos?
Las sugerencias anteriores a esta publicación incluyen:
-
pd.DataFrame.set_value
está en desuso desde Pandas versión 0.21 -
pd.DataFrame.ix
está en deprecated -
pd.DataFrame.loc
está bien, pero puede funcionar en indexadores de matriz y puede hacerlo mejor
Mi recomendación
Use pd.DataFrame.at
for i in df.index:
if <something>:
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 <something> else y
Puede asignar valores en el bucle usando df.set_value:
for i, row in df.iterrows():
ifor_val = something
if <condition>:
ifor_val = something_else
df.at[i,''ifor''] = ifor_val
si no necesita los valores de la fila, simplemente podría iterar sobre los índices de df, pero conservé el for-loop original en caso de que necesite el valor de la fila para algo que no se muestra aquí.
Un método que puede usar es itertuples()
, itera sobre filas de DataFrame como namedtuples, 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 <something>:
df.loc[row.Index, ''ifor''] = x
else:
df.loc[row.Index, ''ifor''] = x
df.loc[row.Index, ''ifor''] = x
for i, row in df.iterrows():
if <something>:
df.at[i, ''ifor''] = x
else:
df.at[i, ''ifor''] = y