Una delle cose fastidiose che tutti stiamo cercando di capire quando impariamo Pandas è la distinzione tra .loc
e .iloc
.
Mettiamo fine a questa confusione e chiarire la differenza tra questi due metodi. Darò molti esempi e spero che la distinzione sarà molto più chiara alla fine di questo articolo.
Cos’è .loc e .iloc in Pandas?
Sia .loc
che .iloc
sono attributi essenziali dei DataFrame di Pandas e entrambi vengono utilizzati per selezionare sottoinsiemi specifici di dati. Il loro scopo è accedere e consentire la manipolazione di una parte specifica del DataFrame anziché dell’intero DataFrame.
Caratteristica |
.loc |
.iloc |
Sintassi |
df.loc[indice_righe, indice_colonne] |
df.iloc[indice_righe, indice_colonne] |
Metodo di indicizzazione |
Indicizzazione basata su etichette |
Indicizzazione basata sulla posizione |
Usato per il riferimento |
Etichette (nomi) delle righe e delle colonne |
Indici numerici delle righe e delle colonne (a partire da 0) |
Come possiamo vedere dalla tabella, la sintassi appare molto simile. La differenza risiede nell’uso degli argomenti row_indexer
e column_indexer
. Questo perché i due metodi offrono approcci diversi all’indicizzazione dei dati: mentre .loc
indicizza in base ai nomi delle etichette, .iloc
utilizza gli indici di posizione numerica delle righe e delle colonne come argomenti.
Esaminiamo ora nel dettaglio ciascuno dei due metodi, iniziando da .loc
.
Usando .loc: Selezione per etichette
Per illustrare i concetti, consideriamo un ipotetico database clienti rappresentato da questo DataFrame chiamato df
, con il ID Cliente
che rappresenta l’indice di riga:
ID Cliente |
Nome |
Paese |
Regione |
Età |
C123 |
John Doe |
Stati Uniti |
America del Nord |
67 |
C234 |
Petra Müller |
Germania |
Europa |
51 |
C345 |
Ali Khan |
Pakistan |
Asia |
19 |
C456 |
Maria Gonzalez |
Mexico |
North America |
26 |
C567 |
David Lee |
China |
Asia |
40 |
There sono quattro modi principali per selezionare righe con .loc
. Questi includono:
- Selezione di una singola riga
- Selezione di righe multiple
- Selezione di un insieme di righe
- Selezione condizionale delle righe
Selezione di una singola riga usando .loc
Per selezionare una singola riga, utilizziamo l’etichetta della riga che vogliamo recuperare come row_indexer
. Di conseguenza, la sintassi appare così: df.loc['etichetta_riga']
. Utilizziamo questo metodo per visualizzare tutte le informazioni sul nostro cliente Ali Khan:
df.loc['C345']
C345 |
|
Nome |
Ali Khan |
Paese |
Pakistan |
Regione |
Asia |
Età |
19 |
Selezionare più righe utilizzando .loc
Se vogliamo selezionare più righe che non seguono necessariamente un ordine, dobbiamo passare un elenco delle loro etichette di riga come argomento row_indexer
. Questo significa che dobbiamo utilizzare non uno ma due coppie di parentesi quadre: una per la sintassi regolare di .loc
e una per l’elenco delle etichette.
La riga df.loc[['row_label_1', 'row_label_2']]
restituirà le due righe del DataFrame df
specificate nell’elenco. Diciamo che volessimo conoscere non solo le informazioni su Ali Khan ma anche su David Lee:
df.loc[['C345', 'C567']]
ID Cliente |
Nome |
Paese |
Regione |
Età |
C345 |
Ali Khan |
Pakistan |
Asia |
19 |
C567 |
David Lee |
Cina |
Asia |
40 |
Selezione di un intervallo di righe utilizzando .loc
Possiamo selezionare un intervallo di righe passando le etichette della prima e dell’ultima riga con due punti in mezzo: df.loc['etichetta_riga_iniziale':'etichetta_riga_finale']
. Possiamo visualizzare le prime quattro righe del nostro DataFrame in questo modo:
df.loc['C123' : 'C456']
ID Cliente |
Nome |
Paese |
Regione |
Data di Registrazione |
C123 |
John Doe |
Stati Uniti |
America del Nord |
67 |
C234 |
Petra Müller |
Germania |
Europa |
51 |
C345 |
Ali Khan |
Pakistan |
Asia |
19 |
C456 |
Maria Gonzalez |
Messico |
America del Nord |
26 |
Ci sono due cose da tenere a mente qui:
- L’output include la riga specificata in
row_label_end
. Questo è diverso in.iloc
, che tratteremo più avanti. - Utilizziamo solo una coppia di parentesi quadre, anche se vogliamo recuperare più righe. Non utilizziamo una lista per specificare le varie righe, quindi utilizzare due parentesi quadre restituirebbe un
SyntaxError
.
Selezione condizionale delle righe usando .loc
Possiamo anche restituire righe basate su un’espressione condizionale. Possiamo filtrare tutte le righe in base al fatto che soddisfino o meno una certa condizione e visualizzare solo quelle che lo fanno.
La sintassi corrispondente è df.loc[conditional_expression]
, con la conditional_expression
che è un’affermazione sui valori consentiti in una colonna specifica.
Per colonne con dati non numerici (come Name
o Country
), l’istruzione può utilizzare solo l’operatore uguale o disuguale, poiché non c’è un ordine tra i valori. Potremmo, ad esempio, restituire tutte le righe dei clienti che non sono dell’Asia:
df.loc[df['Region'] != 'Asia']
ID Cliente |
Nome |
Paese |
Regione |
Età |
C123 |
John Doe |
Stati Uniti |
Nord America |
67 |
C234 |
Petra Müller |
Germania |
Europa |
51 |
C456 |
Maria Gonzalez |
Messico |
Nord America |
26 |
La selezione di una singola colonna utilizzando .loc
Per selezionare colonne, dobbiamo specificare l’argomento column_indexer
, che viene dopo l’argomento row_indexer
. Se vogliamo specificare solo il column_indexer
, dobbiamo in qualche modo indicare che vogliamo restituire tutte le righe e filtrare solo sulle colonne. Vediamo come possiamo farlo!
La selezione di una singola colonna può essere fatta specificando il column_indexer
con l’etichetta della rispettiva colonna. Per recuperare tutte le righe, dobbiamo specificare il row_indexer
con un semplice due punti. Arriviamo a una sintassi che appare così: df.loc[:, 'nome_colonna']
.
Mostriamo il Nome
di ciascun cliente:
df.loc[:, 'Name']
ID Cliente |
Nome |
C123 |
John Doe |
C234 |
Petra Müller |
C345 |
Ali Khan |
C456 |
Maria Gonzalez |
C567 |
David Lee |
Selezione di più colonne usando .loc
Simile alla selezione di più righe, dobbiamo passare un elenco di etichette di colonne se vogliamo restituire più colonne di un DataFrame che non seguono necessariamente l’ordine: df.loc[:, [col_label_1, 'col_label_2']]
.
Supponendo che volessimo aggiungere l’età di tutti i clienti al nostro ultimo output, funzionerebbe così:
df.loc[:, ['Name', 'Age']]
ID cliente |
Nome |
Età |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
Ali Khan |
19 |
C456 |
Maria Gonzalez |
26 |
C567 |
David Lee |
40 |
Selezione di una serie di colonne utilizzando .loc
Utilizzare i due punti tra le etichette di due colonne selezionerà tutte le colonne nell’intervallo di ordine tra le due colonne specificate. È inclusiva della colonna finale, il che significa che anche la colonna chiamata col_end
sarà selezionata nella sintassi standard, che è la seguente: df.loc[:, 'col_start':'col_end']
.
Se fossimo interessati al Nome
, Paese
e Regione
dei nostri clienti, la nostra riga di codice potrebbe essere:
df.loc[:, 'Name':'Region']
ID Cliente |
Nome |
Paese |
Regione |
C123 |
John Doe |
Stati Uniti |
America del Nord |
C234 |
Petra Müller |
Germania |
Europa |
C345 |
Ali Khan |
Pakistan |
Asia |
C456 |
Maria Gonzalez |
Messico |
America del Nord |
C567 |
David Lee |
Cina |
Asia |
Selezione combinata di righe e colonne utilizzando .loc
È anche possibile specificare sia il row_indexer
che il column_indexer
. Questo potrebbe essere utilizzato per recuperare un singolo pezzo di informazione, ovvero una cella del DataFrame. Per fare ciò, specifichiamo una riga e una colonna utilizzando la sintassi df.loc['row_label', 'column_name']
.
Il caso più utile è restituire un sub-DataFrame che si concentra esattamente sul set di righe e colonne di nostro interesse. È possibile specificare entrambi gli indexer come liste utilizzando le parentesi quadre, o come uno slice utilizzando i due punti, e persino combinarlo con un’espressione condizionale per la selezione delle righe.
Ecco un esempio di restituzione del Name
, Country
e Region
di ciascun cliente con un Age
superiore a 30:
df.loc[df['Age'] > 30, 'Name':'Region']
ID Cliente |
Nome |
Paese |
Regione |
C123 |
John Doe |
Stati Uniti |
Nord America |
C234 |
Petra Müller |
Germany |
Europe |
C567 |
David Lee |
China |
Asia |
Utilizzando .iloc: Selezione per posizione intera
.iloc
seleziona per posizione anziché per etichetta. Questa è la sintassi standard per utilizzare .iloc
: df.iloc[indice_riga, indice_colonna]
. Ci sono due cose speciali da tenere d’occhio:
- Conteggio a partire da 0: La prima riga e colonna hanno l’indice 0, la seconda indice 1, ecc.
- Esclusività del valore di fine dell’intervallo: Quando si utilizza una fetta, la riga o colonna specificata dopo i due punti non è inclusa nella selezione.
Selezione di una singola riga utilizzando .iloc
Una singola riga può essere selezionata utilizzando l’intero che rappresenta il numero di indice della riga come indice_riga
. Non abbiamo bisogno di virgolette poiché stiamo inserendo un numero intero e non una stringa di etichetta come abbiamo fatto con .loc
. Per restituire la prima riga di un DataFrame chiamato df
, inserire df.iloc[0]
.
Nel nostro esempio di DataFrame, questa riga di codice restituisce le informazioni di John Doe:
df.iloc[0]
C123 |
|
Name |
John Doe |
Country |
Stati Uniti |
Regione |
North America |
Età |
67 |
Selezionare più righe utilizzando .iloc
Selezionare più righe funziona in .iloc
come in .loc
—inseriamo gli indici di riga come interi in una lista con parentesi quadre. La sintassi è simile a questa: df.iloc[[0, 3, 4]]
.
L’output rispettivo nella nostra tabella dei clienti può essere visto di seguito:
df.iloc[[0, 3, 4]]
ID Cliente |
Nome |
Paese |
Regione |
Età |
C123 |
John Doe |
Stati Uniti |
America del Nord |
67 |
C456 |
Maria Gonzalez |
Messico |
America del Nord |
26 |
C567 |
David Lee |
Cina |
Asia |
40 |
Selezionare una fetta di righe utilizzando .iloc
Per selezionare una fetta di righe, utilizziamo i due interi di indice di riga specificati. Ora, dobbiamo prestare attenzione all’esclusività menzionata in precedenza.
Possiamo prendere la riga df.iloc[1:4]
come esempio per illustrare questo concetto. Il numero di indice 1 significa la seconda riga, quindi la nostra fetta inizia da lì. L’intero di indice 4 rappresenta la quinta riga, ma poiché .iloc
non è inclusivo per la selezione della fetta, il nostro output includerà tutte le righe fino all’ultima prima di questa. Pertanto, restituirà la seconda, terza e quarta riga.
Dimostriamo che la riga funziona come dovrebbe:
df.iloc[1:4]
ID cliente |
Nome |
Paese |
Regione |
Età |
C234 |
Petra Müller |
Germania |
Europa |
51 |
C345 |
Ali Khan |
Pakistan |
Asia |
19 |
C456 |
Maria Gonzalez |
Messico |
America del Nord |
26 |
Selezione di una singola colonna utilizzando .iloc
La logica di selezione delle colonne usando .iloc
segue quanto appreso finora. Vediamo come funziona per singole colonne, colonne multiple e fette di colonne.
Come con .loc
, è importante specificare il row_indexer
prima di procedere al column_indexer
. Per recuperare i valori della terza colonna di df
per ogni riga, inseriamo df.iloc[:, 2]
.
Poiché Region
è la terza colonna nel nostro DataFrame, verrà recuperata come conseguenza di quella riga di codice:
df.iloc[:, 2]
ID Cliente |
Regione |
C123 |
America del Nord |
C234 |
Europa |
C345 |
Asia |
C456 |
America del Nord |
C567 |
Asia |
Selezionare più colonne utilizzando .iloc
Per selezionare più colonne che non sono necessariamente successive, possiamo inserire nuovamente una lista contenente interi come column_indexer
. La riga df.iloc[:, [0, 3]]
restituisce sia la prima che la quarta colonna.
Nel nostro caso, le informazioni visualizzate sono il Nome
e l’Età
di ciascun cliente:
df.iloc[:, [0, 3]]
ID Cliente |
Nome |
Età |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
Ali Khan |
19 |
C456 |
Maria Gonzalez |
26 |
C567 |
David Lee |
40 |
Selezione di una porzione di colonne utilizzando .iloc
Per la selezione delle colonne utilizzando .iloc
, la logica del column_indexer
segue quella del row_indexer
. La colonna rappresentata dall’intero dopo i due punti non è inclusa nell’output. Per recuperare la seconda e la terza colonna, il codice dovrebbe essere simile a questo: df.iloc[:, 1:3]
.
Questa riga qui sotto restituisce tutte le informazioni geografiche che abbiamo sui nostri clienti:
df.iloc[:, 1:3]
ID Cliente |
Paese |
Regione |
C123 |
Stati Uniti |
Nord America |
C234 |
Germania |
Europa |
C345 |
Pakistan |
Asia |
C456 |
Messico |
Nord America |
C567 |
Cina |
Asia |
Selezione combinata di righe e colonne utilizzando .iloc
Possiamo mettere insieme ciò che abbiamo imparato su .iloc
per combinare la selezione di righe e colonne. Ancora una volta, è possibile restituire una singola cella o un sotto-DataFrame. Per restituire la cella singola all’intersezione della riga 3 e della colonna 4, inseriamo df.iloc[2, 3]
.
Proprio come con .loc
, possiamo specificare entrambi gli indexer come liste utilizzando le parentesi quadre, o come una fetta utilizzando i due punti. Se vogliamo selezionare righe utilizzando espressioni condizionali, tecnicamente è possibile anche con .iloc
, ma non è consigliato. Utilizzare i nomi delle etichette e .loc
è di solito molto più intuitivo e meno soggetto a errori.
Questo ultimo esempio mostra Paese
, Regione
e Età
per la prima, seconda e quinta riga del nostro DataFrame:
df.iloc[[0,1,4], 1:4]
ID Cliente |
Paese |
Regione |
Età |
C123 |
Stati Uniti |
America del Nord |
67 |
C234 |
Germania |
Europa |
51 |
C567 |
Cina |
Asia |
40 |
.iloc vs .loc: Quando usare quale
Generalmente, c’è una regola semplice da seguire in base alla quale la scelta del metodo dipende dalla tua conoscenza del DataFrame:
- Usa
.loc
quando conosci le etichette (nomi) delle righe/colonne. - Usa
.iloc
quando conosci le posizioni intere delle righe/colonne.
Alcuni scenari favoriscono l’uso di .loc
o .iloc
per loro natura. Ad esempio, iterare sulle righe o sulle colonne è più semplice e intuitivo utilizzando numeri interi anziché etichette. Come abbiamo già menzionato, filtrare le righe basandosi su condizioni sui valori delle colonne è meno soggetto a errori utilizzando i nomi delle colonne.
Scenari che favoriscono .loc |
Scenari che favoriscono .iloc |
Il tuo DataFrame ha nomi significativi per indice/colonne. |
Stai iterando sulle righe/colonne in base alla loro posizione. |
Devi filtrare in base alle condizioni sui valori delle colonne. |
I nomi degli indici/colonne non sono rilevanti per il tuo compito. |
KeyError, NameError e Index Error Con .loc e .iloc
Diamo un’occhiata ai possibili problemi. Un errore comune nell’uso di .loc
è l’incontro di un KeyError
. Questo errore si verifica quando cerchiamo di accedere a un’etichetta di riga o colonna che non esiste nel nostro DataFrame. Per evitarlo, dobbiamo sempre assicurarci che le etichette che stiamo usando siano corrette e corrispondano alle etichette esistenti nel nostro DataFrame e controllare due volte alla ricerca di errori di battitura.
Inoltre, è importante usare sempre le virgolette per le etichette specificate con .loc
. Dimenticarle restituirà un NameError
.
Un IndexError
può verificarsi quando si utilizza .iloc
se specifichiamo una posizione intera che è al di fuori dell’intervallo valido degli indici del nostro DataFrame. Ciò accade quando l’indice che si sta cercando di accedere non esiste, sia perché si trova oltre il numero di righe o colonne nel DataFrame o perché è un valore negativo. Per prevenire questo errore, controlla le dimensioni del tuo DataFrame e utilizza valori di indice appropriati all’interno dell’intervallo valido.
Conclusion
Spero che questo blog sia stato utile e che la distinzione tra .loc
e .iloc
sia ora chiara. Per saperne di più, ecco alcuni buoni passi successivi: