Skip to content

pandas: Iterare DataFrame con il ciclo “for”.

Python

Se pandas.DataFrame viene passato dal ciclo per così com’è, vengono restituiti i nomi delle colonne. Puoi scorrere colonne e righe di pandas.DataFrame con i metodi iteritemi(), iterrows() e itertuple().

In questo articolo vengono descritti i seguenti contenuti.

  • Iterare pandas.DataFrame nel ciclo per così com’è
  • Iterare le colonne di pandas.DataFrame
  • Iterare le righe di pandas.DataFrame
    • DataFrame.iterrows()
    • DataFrame.itertuples()
  • Iterare solo colonne specifiche
  • Aggiorna i valori nel ciclo per
  • Confronto di velocità

Per ulteriori informazioni sull’istruzione per in Python, vedere l’articolo seguente.

Usa il seguente pandas.DataFrame come esempio.

import pandas as pd
import numpy as np

df = pd.DataFrame({'age': [24, 42], 'state': ['NY', 'CA'], 'point': [64, 92]},
                  index=['Alice', 'Bob'])

print(df)
#        age state  point
# Alice   24    NY     64
# Bob     42    CA     92

Iterare pandas.DataFrame nel ciclo per così com’è

Se ripeti pandas.DataFrame in un ciclo per così com’è, i nomi delle colonne vengono restituiti in ordine.

for column_name in df:
    print(column_name)
# age
# state
# point

Iterare le colonne di pandas.DataFrame

DataFrame.iteritems()

Il metodo sulle iteritems() scorre sulle colonne e riporta (nome colonna, serie), una tupla con il nome della colonna e il contenuto come pandas.Series.

for column_name, item in df.iteritems():
    print(column_name)
    print('------')
    print(type(item))
    print(item)
    print('------')
    print(item[0], item['Alice'], item.Alice)
    print(item[1], item['Bob'], item.Bob)
    print('======n')
# age
# ------
# <class 'pandas.core.series.Series'>
# Alice    24
# Bob      42
# Name: age, dtype: int64
# ------
# 24 24 24
# 42 42 42
# ======
# 
# state
# ------
# <class 'pandas.core.series.Series'>
# Alice    NY
# Bob      CA
# Name: state, dtype: object
# ------
# NY NY NY
# CA CA CA
# ======
# 
# point
# ------
# <class 'pandas.core.series.Series'>
# Alice    64
# Bob      92
# Name: point, dtype: int64
# ------
# 64 64 64
# 92 92 92
# ======
# 

Iterare le righe di pandas.DataFrame

I metodi iterrows() e itertules() eseguono l’iterazione sulle righe. Il metodo itertuples() è più veloce.

Se sono necessari solo i valori per una determinata colonna, è ancora più veloce scorrere gli elementi di una determinata colonna individualmente, come spiegato di seguito. I risultati del confronto di velocità sono mostrati alla fine.

DataFrame.iterrows()

Il metodo iterrows() scorre su righe e restituisce (indice, serie), una tupla con l’indice e il contenuto come pandas.Series.

for index, row in df.iterrows():
    print(index)
    print('------')
    print(type(row))
    print(row)
    print('------')
    print(row[0], row['age'], row.age)
    print(row[1], row['state'], row.state)
    print(row[2], row['point'], row.point)
    print('======n')
# Alice
# ------
# <class 'pandas.core.series.Series'>
# age      24
# state    NY
# point    64
# Name: Alice, dtype: object
# ------
# 24 24 24
# NY NY NY
# 64 64 64
# ======
# 
# Bob
# ------
# <class 'pandas.core.series.Series'>
# age      42
# state    CA
# point    92
# Name: Bob, dtype: object
# ------
# 42 42 42
# CA CA CA
# 92 92 92
# ======
# 

DataFrame.itertuples()

Il metodo sulle righe itertuples() scorre e restituisce una tupla dell’indice e del contenuto. Il primo elemento della tupla è l’indice.

Per definizione predefinita, restituisce una tupla denominata Pandas. Poiché è una namedtuple, puoi accedere al valore di ogni elemento tramite . così vieni [].

for row in df.itertuples():
    print(type(row))
    print(row)
    print('------')
    print(row[0], row.Index)
    print(row[1], row.age)
    print(row[2], row.state)
    print(row[3], row.point)
    print('======n')
# <class 'pandas.core.frame.Pandas'>
# Pandas(Index='Alice', age=24, state="NY", point=64)
# ------
# Alice Alice
# 24 24
# NY NY
# 64 64
# ======
# 
# <class 'pandas.core.frame.Pandas'>
# Pandas(Index='Bob', age=42, state="CA", point=92)
# ------
# Bob Bob
# 42 42
# CA CA
# 92 92
# ======
# 

Viene restituita una tupla normale se il parametro viene impostato su None.

for row in df.itertuples(name=None):
    print(type(row))
    print(row)
    print(row[0], row[1], row[2], row[3])
    print('======n')
# <class 'tuple'>
# ('Alice', 24, 'NY', 64)
# Alice 24 NY 64
# ======
# 
# <class 'tuple'>
# ('Bob', 42, 'CA', 92)
# Bob 42 CA 92
# ======
# 

Iterare solo colonne specifiche

Se hai bisogno solo degli elementi di una particolare colonna, puoi anche scrivere come segue.

La colonna pandas.DataFrame è pandas.Series.

print(df['age'])
# Alice    24
# Bob      42
# Name: age, dtype: int64

print(type(df['age']))
# <class 'pandas.core.series.Series'>

Se applichi pandas.Series a un ciclo for, puoi ottenere i suoi valori in ordine. Puoi ottenere i valori di quella colonna in ordine specificando una colonna di pandas.DataFrame e applicandola a un ciclo for.

for age in df['age']:
    print(age)
# 24
# 42

Puoi anche ottenere i valori di più colonne con la funzione zip() incorporata.

for age, point in zip(df['age'], df['point']):
    print(age, point)
# 24 64
# 42 92

Utilizzare l’attributo index se si desidera ottenere l’indice. Vieni nell’esempio sopra, puoi metterlo insieme ad altre colonne tramite zip().

print(df.index)
# Index(['Alice', 'Bob'], dtype="object")

print(type(df.index))
# <class 'pandas.core.indexes.base.Index'>

for index in df.index:
    print(index)
# Alice
# Bob

for index, state in zip(df.index, df['state']):
    print(index, state)
# Alice NY
# Bob CA

Aggiorna i valori nel ciclo per

Il pandas.Series restituito dal metodo iterrows() è una copia, non una vista, quindi modificarlo non aggiornerà i dati originali.

for index, row in df.iterrows():
    row['point'] += row['age']

print(df)
#        age state  point
# Alice   24    NY     64
# Bob     42    CA     92

Puoi aggiornarlo selezionando gli elementi del DataFrame originale con at[].

for index, row in df.iterrows():
    df.at[index, 'point'] += row['age']

print(df)
#        age state  point
# Alice   24    NY     88
# Bob     42    CA    134

Vedere il seguente articolo su at[].

Tuttavia, in molti casi, non è necessario utilizzare un ciclo per aggiornare un elemento o aggiungere nuova colonna basata su una colonna esistente. È più semplice e veloce senza scrivere un ciclo per.

Stesso processo senza un ciclo per:

df = pd.DataFrame({'age': [24, 42], 'state': ['NY', 'CA'], 'point': [64, 92]},
                  index=['Alice', 'Bob'])
df['point'] += df['age']
print(df)
#        age state  point
# Alice   24    NY     88
# Bob     42    CA    134

Puoi aggiungere una nuova colonna.

df['new'] = df['point'] + df['age'] * 2
print(df)
#        age state  point  new
# Alice   24    NY     88  136
# Bob     42    CA    134  218

Puoi anche applicare le funzioni NumPy a ciascun elemento di una colonna.

df['age_sqrt'] = np.sqrt(df['age'])
print(df)
#        age state  point  new  age_sqrt
# Alice   24    NY     88  136  4.898979
# Bob     42    CA    134  218  6.480741

Per le stringhe, vengono forniti vari metodi per elaborare direttamente le colonne. Quello che segue è un esempio di conversione in minuscolo e selezione del primo carattere.

df['state_0'] = df['state'].str.lower().str[0]
print(df)
#        age state  point  new  age_sqrt state_0
# Alice   24    NY     88  136  4.898979       n
# Bob     42    CA    134  218  6.480741       c

Confronto di velocità

Confronta la velocità di iterrows(), itertuple() e il metodo per specificare le colonne.

Usa pandas.DataFrame con 100 righe e 10 colonne come esempio. È un semplice esempio con solo elementi numerici, l’indice del nome della riga e le colonne del nome della colonna sono numeri sequenziali predefiniti.

import pandas as pd

df = pd.DataFrame(pd.np.arange(1000).reshape(100, 10))
print(df.shape)
# (100, 10)

print(df.head())
#     0   1   2   3   4   5   6   7   8   9
# 0   0   1   2   3   4   5   6   7   8   9
# 1  10  11  12  13  14  15  16  17  18  19
# 2  20  21  22  23  24  25  26  27  28  29
# 3  30  31  32  33  34  35  36  37  38  39
# 4  40  41  42  43  44  45  46  47  48  49

print(df.tail())
#       0    1    2    3    4    5    6    7    8    9
# 95  950  951  952  953  954  955  956  957  958  959
# 96  960  961  962  963  964  965  966  967  968  969
# 97  970  971  972  973  974  975  976  977  978  979
# 98  980  981  982  983  984  985  986  987  988  989
# 99  990  991  992  993  994  995  996  997  998  999

Si noti che il codice seguente utilizza il comando magico di Jupyter Notebook %%timeit e non funziona se come script Python.

%%timeit
for i, row in df.iterrows():
    pass
# 4.53 ms ± 325 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
for t in df.itertuples():
    pass
# 981 µs ± 43.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
for t in df.itertuples(name=None):
    pass
# 718 µs ± 10.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
for i in df[0]:
    pass
# 15.6 µs ± 446 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%%timeit
for i, j, k in zip(df[0], df[4], df[9]):
    pass
# 46.1 µs ± 588 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%%timeit
for t in zip(df[0], df[1], df[2], df[3], df[4], df[5], df[6], df[7], df[8], df[9]):
    pass
# 147 µs ± 3.78 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

iterrows() è lento perché converte ogni riga in pandas.Series.

itertuple() è più veloce di iterrows(), ma il metodo per specificare le colonne è il più veloce. Nell’ambiente di esempio, è più veloce di itertuple() anche se sono specificate tutte le colonne.

All’aumentare del numero di righe, iterrows() diventa ancora più lento. Dovresti provare a usare itertuples() o la specifica della colonna in questo caso.

Naturalmente, come accennato in precedenza, è meglio non utilizzare il ciclo per se non è necessario.