Tengo un DataFrame
pandas:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Salida:
c1 c2
0 10 100
1 11 110
2 12 120
Ahora quiero iterar sobre las filas de este marco. Para cada fila quiero poder acceder a sus elementos (valores en celdas) por el nombre de las columnas. Por ejemplo:
for row in df.rows:
print row['c1'], row['c2']
¿Es posible hacer eso en pandas?
Encontré esta pregunta similar . Pero no me da la respuesta que necesito. Por ejemplo, se sugiere usar allí:
for date, row in df.T.iteritems():
o
for row in df.iterrows():
Pero no entiendo qué es el row
objeto y cómo puedo trabajar con él.
iter*
Las funciones deben utilizarse en circunstancias muy raras. También relacionado .iterrows
, hay mejores formas de iterar sobre un DataFrame, también podría iterar sobre una lista de listas en ese punto. Si está en el punto en el que no está haciendo nada más que iterar sobre DataFrames, realmente no hay ningún beneficio en usar un DataFrame (suponiendo que iterar sobre él es lo único que está haciendo con él). Solo mi 2c.pandas
es la elección de leer un archivo csv, incluso si el conjunto de datos es pequeño. Simplemente es más fácil programar manipular los datos con las APIRespuestas:
DataFrame.iterrows es un generador que produce tanto índice como fila
fuente
431341610650
donde se lee como4.31E+11
. ¿Hay alguna forma de preservar los tipos?itertuples
, como se explica a continuación. Ver también pandas.pydata.org/pandas-docs/stable/generated/…Respuesta: NO HACER * !
La iteración en los pandas es un antipatrón, y es algo que solo debe hacer cuando haya agotado todas las demás opciones. No debe usar ninguna función con "
iter
" en su nombre durante más de unos pocos miles de filas o tendrá que acostumbrarse a muchas esperas.¿Quieres imprimir un DataFrame? Uso
DataFrame.to_string()
.¿Quieres calcular algo? En ese caso, busque métodos en este orden (lista modificada desde aquí ):
for
bucle de vainilla )DataFrame.apply()
: i) Reducciones que se pueden realizar en cython, ii) Iteración en el espacio pythonDataFrame.itertuples()
yiteritems()
DataFrame.iterrows()
iterrows
yitertuples
(ambos reciben muchos votos en respuestas a esta pregunta) deben usarse en circunstancias muy raras, como generar objetos de fila / tuplas de nombre para procesamiento secuencial, que es realmente lo único para lo que estas funciones son útiles.Apelar a la autoridad
La página de documentos en la iteración tiene un enorme cuadro rojo de advertencia que dice:
* En realidad es un poco más complicado que "no".
df.iterrows()
es la respuesta correcta a esta pregunta, pero "vectorizar sus operaciones" es la mejor. Reconoceré que hay circunstancias en las que no se puede evitar la iteración (por ejemplo, algunas operaciones en las que el resultado depende del valor calculado para la fila anterior). Sin embargo, se necesita cierta familiaridad con la biblioteca para saber cuándo. Si no está seguro de si necesita una solución iterativa, probablemente no. PD: Para saber más sobre mi justificación para escribir esta respuesta, salte al final.Más rápido que el bucle: vectorización , Cython
Una buena cantidad de operaciones y cálculos básicos son "vectorizados" por pandas (ya sea a través de NumPy o mediante funciones Cythonized). Esto incluye aritmética, comparaciones, (la mayoría) reducciones, remodelación (como pivotar), uniones y operaciones grupales. Consulte la documentación sobre la funcionalidad básica esencial para encontrar un método vectorizado adecuado para su problema.
Si no existe ninguno, siéntase libre de escribir el suyo usando extensiones de cython personalizadas .
Siguiente mejor cosa: Lista de comprensiones *
La lista de comprensiones debe ser su próximo puerto de escala si 1) no hay una solución vectorizada disponible, 2) el rendimiento es importante, pero no lo suficientemente importante como para pasar por la molestia de cifrar su código, y 3) está tratando de realizar una transformación de elementos en tu código Hay una buena cantidad de evidencia que sugiere que las comprensiones de listas son lo suficientemente rápidas (e incluso a veces más rápidas) para muchas tareas comunes de pandas.
La formula es simple,
Si puede encapsular su lógica de negocios en una función, puede usar una comprensión de lista que la llame. Puede hacer que las cosas arbitrariamente complejas funcionen a través de la simplicidad y la velocidad de Python sin procesar.
Las
comprensiones de la lista de advertencias suponen que es fácil trabajar con sus datos; lo que eso significa es que sus tipos de datos son consistentes y no tiene NaN, pero esto no siempre se puede garantizar.
zip(df['A'], df['B'], ...)
lugar de hacerlo,df[['A', 'B']].to_numpy()
ya que este último implícitamente eleva los datos al tipo más común. Como ejemplo, si A es numérico y B es una cadena,to_numpy()
convertirá toda la matriz en una cadena, que puede no ser lo que desea. Afortunadamente, hacerzip
ping en las columnas es la solución más sencilla para esto.* YMMV por los motivos descritos en la sección Advertencias anterior.
Un ejemplo obvio
Demostremos la diferencia con un ejemplo simple de agregar dos columnas de pandas
A + B
. Esta es una operación vectorizable, por lo que será fácil contrastar el rendimiento de los métodos discutidos anteriormente.Código de evaluación comparativa, para su referencia.
Sin embargo, debo mencionar que no siempre es así de seco. A veces, la respuesta a "cuál es el mejor método para una operación" es "depende de sus datos". Mi consejo es probar diferentes enfoques en sus datos antes de decidirse por uno.
Otras lecturas
10 minutos para pandas y funcionalidad básica esencial : enlaces útiles que le presentan a los pandas y su biblioteca de funciones vectorizadas * / cythonized.
Mejora del rendimiento : una introducción de los documentos sobre cómo mejorar las operaciones estándar de pandas
¿Son realmente malos los bucles for en los pandas? ¿Cuándo debería importarme? - un escrito detallado por mí sobre las comprensiones de listas y su idoneidad para diversas operaciones (principalmente las que involucran datos no numéricos)
¿Cuándo debería querer usar pandas apply () en mi código? -
apply
es lento (pero no tan lento como laiter*
familia. Sin embargo, hay situaciones en las que uno puede (o debe) considerarapply
como una alternativa seria, especialmente en algunasGroupBy
operaciones).* Los métodos de cadena de pandas están "vectorizados" en el sentido de que se especifican en la serie pero operan en cada elemento. Los mecanismos subyacentes siguen siendo iterativos, porque las operaciones de cadena son inherentemente difíciles de vectorizar.
¿Por qué escribí esta respuesta?
Una tendencia común que noto de los nuevos usuarios es hacer preguntas de la forma "¿cómo puedo iterar sobre mi df para hacer X?". Mostrando código que llama
iterrows()
mientras hace algo dentro de un bucle for. Aquí es por qué. Un nuevo usuario de la biblioteca que no haya sido introducido al concepto de vectorización probablemente visualizará el código que resuelve su problema al iterar sobre sus datos para hacer algo. Sin saber cómo iterar sobre un DataFrame, lo primero que hacen es buscarlo en Google y terminar aquí, en esta pregunta. Luego ven la respuesta aceptada que les dice cómo hacerlo, y cierran los ojos y ejecutan este código sin preguntarse primero si la iteración no es lo correcto.El objetivo de esta respuesta es ayudar a los nuevos usuarios a comprender que la iteración no es necesariamente la solución a cada problema, y que podrían existir soluciones mejores, más rápidas y más idiomáticas, y que vale la pena invertir tiempo en explorarlas. No estoy tratando de comenzar una guerra de iteración contra vectorización, pero quiero que los nuevos usuarios estén informados cuando desarrollen soluciones a sus problemas con esta biblioteca.
fuente
zip(df['A'], df['B'])
lugar dedf.iterrows()
.iterrows()
iteración y denunciarla de forma implícita siempre que existan mejores alternativas.for
los bucles por sí solos están bien, pero las comprensiones de listas son mejores si realiza transformaciones iterativas por elementos.DataFrame.values
convertirá cada columna a un tipo de datos común.DataFrame.to_numpy()
hace esto también Afortunadamente podemos usarzip
con cualquier cantidad de columnas.Primero considere si realmente necesita iterar sobre filas en un DataFrame. Vea esta respuesta para alternativas.
Si aún necesita iterar sobre filas, puede usar los métodos a continuación. Tenga en cuenta algunas advertencias importantes que no se mencionan en ninguna de las otras respuestas.
DataFrame.iterrows ()
DataFrame.itertuples ()
itertuples()
se supone que es más rápido queiterrows()
Pero tenga en cuenta, de acuerdo con los documentos (pandas 0.24.2 en este momento):
Iterrows:
dtype
podría no coincidir de fila a filaIterrows: no modifique filas
Utilice DataFrame.apply () en su lugar:
itertuples:
Vea los documentos de pandas en iteración para más detalles.
fuente
for row in df[['c1','c2']].itertuples(index=True, name=None):
incluir solo ciertas columnas en el iterador de fila.getattr(row, "c1")
, puedes usar solorow.c1
.getattr(row, "c1")
lugar derow.c1
, pierde cualquier ventaja de rendimiento deitertuples
, y si realmente necesita llegar a la propiedad a través de una cadena, debe usar iterrows en su lugar.numba
ycython
(los mismos documentos dicen que "siempre vale la pena optimizar en Python primero"). Escribí esta respuesta para ayudar a otros a evitar problemas (a veces frustrantes) ya que ninguna de las otras respuestas menciona estas advertencias. Engañar a alguien o decir "eso es lo correcto" nunca fue mi intención. He mejorado la respuesta.Deberías usar
df.iterrows()
. Aunque iterar fila por fila no es especialmente eficiente ya que losSeries
objetos tienen que ser creados.fuente
Si bien
iterrows()
es una buena opción, a vecesitertuples()
puede ser mucho más rápido:fuente
for a,b,c in izip(df["a"],df["b"],df["c"]:
es casi igual de rápido.iterrows()
encajona cada fila de datos en una Serie, mientrasitertuples()
que no.df
se crea a partir de un diccionario, por lo querow[1]
podría referirse a cualquiera de las columnas. Resulta que los tiempos son más o menos los mismos para el entero frente a las columnas flotantes.También puedes usar
df.apply()
para iterar sobre filas y acceder a múltiples columnas para una función.docs: DataFrame.apply ()
fuente
apply
no se "itera" sobre las filas, sino que aplica una función en fila. El código anterior no funcionaría si realmente haces iteraciones necesidad y Indices de, por ejemplo, al comparar los valores a través de diferentes filas (en ese caso se puede hacer nada más que la iteración).Puede usar la función df.iloc de la siguiente manera:
fuente
itertuples
conserva los tipos de datos, pero elimina cualquier nombre que no le guste.iterrows
hace lo contrariofor i in range(df.shape[0])
puede acelerar este enfoque un poco, todavía es aproximadamente 3.5 veces más lento que el enfoque iterrows () anterior para mi aplicación.my_iter = df.itertuples()
toma el doble de memoria y mucho tiempo para copiarlo. mismo paraiterrows()
.Estaba buscando Cómo iterar en filas Y columnas y terminé aquí, así:
fuente
Puedes escribir tu propio iterador que implemente
namedtuple
Esto es directamente comparable a
pd.DataFrame.itertuples
. Mi objetivo es realizar la misma tarea con más eficiencia.Para el marco de datos dado con mi función:
O con
pd.DataFrame.itertuples
:Una prueba completa
Probamos hacer que todas las columnas estén disponibles y subconjunto de las columnas.
fuente
intertuples
, la línea naranja es una lista de un iterador a través de un bloque de rendimiento.interrows
No se compara.¿Cómo iterar eficientemente?
Si realmente tiene que iterar un marco de datos de pandas, probablemente querrá evitar usar iterrows () . Existen diferentes métodos y lo habitual
iterrows()
está lejos de ser el mejor. itertuples () puede ser 100 veces más rápido.En breve:
df.itertuples(name=None)
. En particular, cuando tiene un número fijo de columnas y menos de 255 columnas. Ver punto (3)df.itertuples()
excepto si sus columnas tienen caracteres especiales como espacios o '-'. Ver punto (2)itertuples()
incluso si su marco de datos tiene columnas extrañas usando el último ejemplo. Ver punto (4)iterrows()
si no puede las soluciones anteriores. Ver punto (1)Diferentes métodos para iterar sobre filas en un marco de datos de pandas:
Genere un marco de datos aleatorio con un millón de filas y 4 columnas:
1) Lo habitual
iterrows()
es conveniente pero muy lento:2) El valor predeterminado
itertuples()
ya es mucho más rápido, pero no funciona con nombres de columna comoMy Col-Name is very Strange
(debe evitar este método si sus columnas se repiten o si el nombre de una columna no se puede convertir simplemente en un nombre de variable de Python):3) El valor predeterminado
itertuples()
usando name = None es aún más rápido pero realmente no es conveniente ya que debe definir una variable por columna.4) Finalmente, el nombre
itertuples()
es más lento que el punto anterior, pero no tiene que definir una variable por columna y funciona con nombres de columna comoMy Col-Name is very Strange
.Salida:
Este artículo es una comparación muy interesante entre iterrows e itertuples
fuente
Para recorrer todas las filas en un
dataframe
puede usar:fuente
fuente
A veces un patrón útil es:
Lo que resulta en:
fuente
Para bucle todas las filas de una
dataframe
y de uso de los valores de cada fila convenientemente ,namedtuples
pueden ser convertidos andarray
s. Por ejemplo:Iterando sobre las filas:
resultados en:
Tenga en cuenta que si
index=True
, se añade el índice como el primer elemento de la tupla , que puede ser indeseable para algunas aplicaciones.fuente
Hay una forma de iterar filas de lanzamiento mientras se obtiene un DataFrame a cambio, y no una Serie. No veo que nadie mencione que puede pasar el índice como una lista para que la fila se devuelva como un Marco de datos:
Tenga en cuenta el uso de corchetes dobles. Esto devuelve un DataFrame con una sola fila.
fuente
Para ver y modificar valores, usaría
iterrows()
. En un bucle for y usando el desempaquetado de tuplas (vea el ejemplo:)i, row
, usorow
solo para ver el valor y lo usoi
con elloc
método cuando quiero modificar los valores. Como se indicó en respuestas anteriores, aquí no debe modificar algo sobre lo que está iterando.Aquí,
row
en el bucle hay una copia de esa fila, y no una vista de ella. Por lo tanto, NO debe escribir algo comorow['A'] = 'New_Value'
, no modificará el DataFrame. Sin embargo, puede usari
yloc
especificar DataFrame para hacer el trabajo.fuente
Sé que llego tarde a la parte que responde, pero solo quería agregar a la respuesta de @ cs95 anterior, que creo que debería ser la respuesta aceptada. En su respuesta, muestra que la vectorización de pandas supera ampliamente a otros métodos de pandas para calcular cosas con marcos de datos.
Quería agregar que si primero convierte el marco de datos en una matriz numpy y luego usa la vectorización, es aún más rápido que la vectorización de marco de datos pandas (y eso incluye el tiempo para volver a convertirlo en una serie de marco de datos).
Si agrega las siguientes funciones al código de referencia de @ cs95, esto se vuelve bastante evidente:
fuente
También puede hacer
numpy
indexación para acelerar aún más. Realmente no está iterando, pero funciona mucho mejor que la iteración para ciertas aplicaciones.También es posible que desee convertirlo en una matriz. Se supone que estos índices / selecciones ya deben actuar como matrices de Numpy, pero me encontré con problemas y necesitaba emitir
fuente
Hay tantas formas de iterar sobre las filas en el marco de datos de pandas. Una forma muy simple e intuitiva es:
fuente
Este ejemplo usa iloc para aislar cada dígito en el marco de datos.
fuente
Algunas bibliotecas (por ejemplo, una biblioteca de interoperabilidad de Java que uso) requieren que los valores se pasen en una fila a la vez, por ejemplo, si se transmiten datos. Para replicar la naturaleza de transmisión, 'transmito' mis valores de trama de datos uno por uno, escribí lo siguiente, que es útil de vez en cuando.
Que se puede usar:
Y conserva la asignación de valores / nombres para las filas que se iteran. Obviamente, es mucho más lento que usar apply y Cython como se indicó anteriormente, pero es necesario en algunas circunstancias.
fuente
En breve
Detalles en este video
Punto de referencia
fuente