Cómo iterar sobre filas en un marco de datos de Pandas

Este tutorial explica cómo iterar sobre filas en un DataFrame de Pandas. Utilizará las funciones items(), iterrows() e itertuples() y observará su rendimiento.

Introducción

Pandas es un marco de manipulación de datos inmensamente popular para Python. En muchos casos, es posible que desee iterar sobre los datos, ya sea para imprimirlos o realizar algunas operaciones en ellos.

En este tutorial, veremos cómo iterar filas en un DataFrame de Pandas.

Si eres nuevo en Pandas, puedes leer nuestra tutoría para principiantes. Una vez que esté familiarizado, veamos las tres formas principales de iterar sobre DataFrame:

  • elementos()
  • iterrows()
  • itertuplica()

Iteración de tramas de datos con elementos() {#iteración de tramas de datos con elementos}

Configuremos un DataFrame con algunos datos de personas ficticias:

1
2
3
4
5
6
7
import pandas as pd

df = pd.DataFrame({
    'first_name': ['John', 'Jane', 'Marry', 'Victoria', 'Gabriel', 'Layla'],
    'last_name': ['Smith', 'Doe', 'Jackson', 'Smith', 'Brown', 'Martinez'],
    'age': [34, 29, 37, 52, 26, 32]},
    index=['id001', 'id002', 'id003', 'id004', 'id005', 'id006'])

Tenga en cuenta que estamos usando id's como nuestro índice DataFrame's. Echemos un vistazo a cómo se ve el DataFrame:

1
print(df.to_string())
1
2
3
4
5
6
7
      first_name last_name  age
id001       John     Smith   34
id002       Jane       Doe   29
id003      Marry   Jackson   37
id004   Victoria     Smith   52
id005    Gabriel     Brown   26
id006      Layla  Martinez   32

Ahora, para iterar sobre este DataFrame, usaremos la función items():

1
df.items()

This returns a generador:

1
<generator object DataFrame.items at 0x7f3c064c1900>

Podemos usar esto para generar pares de col_name y data. Estos pares contendrán un nombre de columna y cada fila de datos para esa columna. Recorramos los nombres de las columnas y sus datos:

1
2
for col_name, data in df.items():
    print("col_name:",col_name, "\ndata:",data)

Esto resulta en:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
col_name: first_name
data: 
id001        John
id002        Jane
id003       Marry
id004    Victoria
id005     Gabriel
id006       Layla
Name: first_name, dtype: object
col_name: last_name
data: 
id001       Smith
id002         Doe
id003     Jackson
id004       Smith
id005       Brown
id006    Martinez
Name: last_name, dtype: object
col_name: age
data: 
id001    34
id002    29
id003    37
id004    52
id005    26
id006    32
Name: age, dtype: int64

Hemos iterado con éxito sobre todas las filas de cada columna. Observe que la columna de índice permanece igual durante la iteración, ya que este es el índice asociado para los valores. Si no define un índice, Pandas enumerará la columna de índice en consecuencia.

También podemos imprimir una fila en particular pasando el número de índice a los datos como lo hacemos con las listas de Python:

1
2
for col_name, data in df.items():
    print("col_name:",col_name, "\ndata:",data[1])

Tenga en cuenta que el índice de la lista tiene un índice cero, por lo que datos [1] se referiría a la segunda fila. Verá esta salida:

1
2
3
4
5
6
col_name: first_name 
data: Jane
col_name: last_name 
data: Doe
col_name: age 
data: 29

También podemos pasar el valor de índice a datos.

1
2
for col_name, data in df.items():
    print("col_name:",col_name, "\ndata:",data['id002'])

La salida sería la misma que antes:

1
2
3
4
5
6
col_name: first_name
data: Jane
col_name: last_name
data: Doe
col_name: age
data: 29

Iterando marcos de datos con iterrows()

Mientras que df.items() itera sobre las filas en forma de columna, haciendo un ciclo para cada columna, podemos usar iterrows() para obtener los datos de fila completos de un índice.

Intentemos iterar sobre las filas con iterrows():

1
2
3
for i, row in df.iterrows():
    print(f"Index: {i}")
    print(f"{row}\n")

En el ciclo for, i representa la columna de índice (nuestro DataFrame tiene índices desde id001 hasta id006) y row contiene los datos para ese índice en todas las columnas. Nuestra salida se vería así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Index: id001
first_name     John
last_name     Smith
age              34
Name: id001, dtype: object

Index: id002
first_name    Jane
last_name      Doe
age             29
Name: id002, dtype: object

Index: id003
first_name      Marry
last_name     Jackson
age                37
Name: id003, dtype: object

...

Del mismo modo, podemos iterar sobre las filas de una determinada columna. Simplemente pasando el número de índice o el nombre de columna a la fila. Por ejemplo, podemos imprimir selectivamente la primera columna de la fila así:

1
2
3
for i, row in df.iterrows():
    print(f"Index: {i}")
    print(f"{row['0']}")

O:

1
2
3
for i, row in df.iterrows():
    print(f"Index: {i}")
    print(f"{row['first_name']}")

Ambos producen esta salida:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Index: id001
John
Index: id002
Jane
Index: id003
Marry
Index: id004
Victoria
Index: id005
Gabriel
Index: id006
Layla

Iteración de marcos de datos con * itertuples () * {# iteración de marcos de datos con itertuples}

La función itertuples() también devolverá un generador, que genera valores de fila en tuplas. Probemos esto:

1
2
for row in df.itertuples():
    print(row)

Verás esto en tu shell de Python:

1
2
3
4
5
6
Pandas(Index='id001', first_name='John', last_name='Smith', age=34)
Pandas(Index='id002', first_name='Jane', last_name='Doe', age=29)
Pandas(Index='id003', first_name='Marry', last_name='Jackson', age=37)
Pandas(Index='id004', first_name='Victoria', last_name='Smith', age=52)
Pandas(Index='id005', first_name='Gabriel', last_name='Brown', age=26)
Pandas(Index='id006', first_name='Layla', last_name='Martinez', age=32)

El método itertuples() tiene dos argumentos: index y name.

Podemos optar por no mostrar la columna de índice configurando el parámetro index en False:

1
2
for row in df.itertuples(index=False):
    print(row)

Nuestras tuplas ya no mostrarán el índice:

1
2
3
4
5
6
Pandas(first_name='John', last_name='Smith', age=34)
Pandas(first_name='Jane', last_name='Doe', age=29)
Pandas(first_name='Marry', last_name='Jackson', age=37)
Pandas(first_name='Victoria', last_name='Smith', age=52)
Pandas(first_name='Gabriel', last_name='Brown', age=26)
Pandas(first_name='Layla', last_name='Martinez', age=32)

Como ya habrás notado, este generador genera tuplas con nombre con el nombre predeterminado de Pandas. Podemos cambiar esto pasando el argumento Personas al parámetro nombre. Puede elegir el nombre que desee, pero siempre es mejor elegir nombres relevantes para sus datos:

1
2
for row in df.itertuples(index=False, name='People'):
    print(row)

Ahora nuestra salida sería:

1
2
3
4
5
6
People(first_name='John', last_name='Smith', age=34)
People(first_name='Jane', last_name='Doe', age=29)
People(first_name='Marry', last_name='Jackson', age=37)
People(first_name='Victoria', last_name='Smith', age=52)
People(first_name='Gabriel', last_name='Brown', age=26)
People(first_name='Layla', last_name='Martinez', age=32)

Rendimiento de iteración con Pandas

La documentación oficial de pandas advierte que la iteración es un proceso lento. Si está iterando sobre un DataFrame para modificar los datos, la vectorización sería una alternativa más rápida. Además, se desaconseja modificar los datos mientras se itera sobre las filas, ya que Pandas a veces devuelve una copia de los datos en la fila y no su referencia, lo que significa que no se cambiarán todos los datos.

Para conjuntos de datos pequeños, puede usar el método to_string() para mostrar todos los datos. Para conjuntos de datos más grandes que tienen muchas columnas y filas, puede usar los métodos head(n) o tail(n) para imprimir las primeras n filas de su DataFrame (el valor predeterminado para n es 5) .

Comparación de velocidad {#comparación de velocidad}

Para medir la velocidad de cada método en particular, los envolvimos en funciones que los ejecutarían 1000 veces y devolverían el tiempo promedio de ejecución.

Para probar estos métodos, utilizaremos las funciones print() y list.append() para proporcionar mejores datos de comparación y cubrir casos de uso comunes. Para decidir un ganador justo, iteraremos sobre DataFrame y usaremos solo 1 valor para imprimir o agregar por ciclo.

Así es como se ven los valores devueltos para cada método:

Por ejemplo, mientras que items() haría un ciclo columna por columna:

1
2
3
4
5
6
7
8
('first_name', 
id001        John
id002        Jane
id003       Marry
id004    Victoria
id005     Gabriel
id006       Layla
Name: first_name, dtype: object)

iterrows() proporcionaría todos los datos de columna para una fila en particular:

1
2
3
4
5
('id001', 
first_name     John
last_name     Smith
age              34
Name: id001, dtype: object)

Y, por último, una sola fila para itertuples() se vería así:

1
Pandas(Index='id001', first_name='John', last_name='Smith', age=34)

Aquí están los resultados promedio en segundos:


Método Velocidad (s) Prueba Función artículos() 1.349279541666571 imprimir() iterrows() 3.4104003086661883 imprimir() itertuplicar() 0.41232967500279 imprimir()



Método Velocidad (s) Prueba Función elementos () 0.006637570998767235 agregar () iterrows() 0.5749766406661365 agregar() itertuplicar() 0.3058610513350383 agregar()


Imprimir valores requerirá más tiempo y recursos que agregarlos en general y nuestros ejemplos no son una excepción. Mientras que itertuples() funciona mejor cuando se combina con print(), el método items() supera a otros dramáticamente cuando se usa para append() y iterrows() sigue siendo el último para cada comparación.

Tenga en cuenta que los resultados de estas pruebas dependen en gran medida de otros factores como el sistema operativo, el entorno, los recursos informáticos, etc. El tamaño de sus datos también tendrá un impacto en sus resultados.

Conclusión

Hemos aprendido a iterar sobre el DataFrame con tres métodos diferentes de Pandas: items(), iterrows(), itertuples(). Dependiendo de tus datos y preferencias puedes utilizar uno de ellos en tus proyectos.