Identificare e rimuovere i valori nulli con pandas

 

I valori nulli possono essere fonti di problemi e fastidiosi grattacapi quando ci accingiamo a lavorare con un set di dati. In questo breve articolo vedremo come identificarli e procedere alla loro rimozione.

Dove sono i valori nulli: df.isnull()

Immaginiamo di avere un dataframe chiamato df e di non sapere se contiene dei valori nulli. Possiamo verificare subito scrivendo:

print(df.isnull())

NB: se all'interno del Jupyter Notebook, si può omettere il comando print, scrivendo semplicemente:

df.isnull()

Ciò che vedremo sarà una versione del nostro dataframe simile a quanto segue:

 

Immagine 1

Come possiamo vedere, per alcune colonne e alcune righe, troviamo l’indicazione True che ci indica che il valore normalmente situato in quella posizione del dataframe è un valore nullo.

Quanti sono i valori nulli: df.isnull().sum()

La visualizzazione ottenuta non è l’ideale se si vuole avere una visione d’insieme. A tale scopo, possiamo aggiungere la funzione sum():

df.isnull().sum()

In questo modo, otterremo una descrizione dettagliata del numero dei valori nulli per ogni colonna del nostro dataframe:

 
Immagine 2

Immagine 2

La colonna con il numero più alto di valori nulli è quella corrispondente a ’“Area”. Invece, la colonna relativa alla data risulta essere la più completa.

Come funziona esattamente?

In Python, ogni valore True corrisponde al numero 1. Al contrario, i valori False sono associati a 0. Quindi ogni valore che risponde True alla funzione isnull() equivale ad 1. Facendone la somma, sapremo il numero esatto dei valori nulli.

Rimuovere i valori nulli: dropna()

Immaginiamo di volere eliminare le righe del nostro dataframe che contengono dei valori nulli. Per farlo, possiamo utilizzare dropna(), aggiungendovi il parametro inplace per far sì che venga applicato alla versione permanente del nostro dataframe.

df.dropna(inplace=True)

In questa maniera, andremo a conservare soltanto le righe 0, 2 e 4 in quanto non presentano nessun valore nullo, come già visto in precedenza.

 
Immagine 3

Immagine 3

Tuttavia questo approccio potrebbe essere un po’ troppo drastico. Infatti, immaginiamo che i nostri dati sono inservibili solo quando abbiamo dei valori nulli nelle colonne “Codice posizione” e "Data”. Per farlo non ci resta che specificare il subset, ovvero la/le colonna/e del dataframe alla quale il comando dropna() verrà applicato:

df.dropna(subset=['Data', 'Codice posizione'], inplace=True)

In questo modo, conserveremo le righe del dataframe a patto che contengano dei dati sia nella colonna “Codice posizione” che in quella relativa alla data.

 
Immagine 4

Immagine 4

Spiegazione approfondita di dropna()

Come spiegato, la funzione dropna() serve ad eliminare i valori nulli. Tuttavia, nell’esempio visto qui sopra, abbiamo esaminato soltanto una ma maniera di utilizzo di questa funzione. In questo breve paragrafo andremo ad approfondire tutte le possibilità che offre.

Righe o colonne: il parametro axis

Nell’esempio fatto in precedenza abbiamo eliminato le righe del dataframe che contentevano dei valori nulli. In realtà, possiamo scegliere se andare ad intervenire sulle righe o sulle colonne specificando il parametro axis.

  • Se vogliamo eliminare le righe che contengono valori nulli possiamo decidere di non far nulla, dato che questo è il funzionamento di default del parametro axis. In alternativa, se vogliamo essere espliciti, possiamo scrivere:

df.dropna(axis='index', inplace=True)

Oppure:

df.dropna(axis=0, inplace=True)
  • Se invece vogliamo eliminare le colonne che contengono valori nulli, dobbiamo specificare uno dei seguenti valori per il parametro axis:

df.dropna(axis='columns', inplace=True)

Oppure:

df.dropna(axis=1, inplace=True)

I criteri dell’eliminazione

Una volta che abbiamo deciso se andare ad eliminare le colonne o le righe che contengono i valori nulli, dobbiamo scegliere in base a quale criterio procederemo all’eliminazione. A questo fine possiamo utilizzare due parametri diversi.

Il parametro how

Andando a specificare il parametro how ci permette di indicare quali righe/colonne eliminare in base a quanti valori nulli esse contengono.

  • Se vogliamo eliminare tutte le righe o tutte le colonne che contengono almeno un valore nullo possiamo scrivere facoltativamente (questo è infatti il funzionamento di default):

#eliminiamo tutte le colonne con almeno un valore nullo
df.dropna(axis='columns', how='any', inplace=True)

#eliminiamo tutte le righe con almeno un valore nullo
df.dropna(axis='index', how='any', inplace=True)
  • Se vogliamo eliminare le righe o le colonne che contengono solo valori nulli, possiamo scrivere:

#eliminiamo tutte le colonne con tutti i valori nulli
df.dropna(axis='columns', how='all', inplace=True)

#eliminiamo tutte le righe con tutti i valori nulli
df.dropna(axis='index', how='all', inplace=True)

Il parametro thresh

Il parametro thresh (abbreviazione di “threshold” che vuol dire “limite”, “soglia”) ci permette di indicare quali righe/colonne andare a conservare in base al numero di valori non nulli che esse contengono. In definitiva, l’approccio del parametro thresh è diametralmente opposto a quello del parametro how descritto in precedenza. Il valore da associare a thresh è necessariamente un numero (tipo int) e si esplicita nella maniera seguente:

#conserviamo le righe che hanno almeno 3 valori non nulli
df.dropna(axis='index', thresh=3, inplace=True)

A titolo di esempio, questa riga di codice, se applicata al dataframe illustrato nell’immagine 1, conserverebbe le righe evidenziate:

 

Immagine 5

In definitiva tutte le righe che contengono almeno 3 False (tenendo a mente che il valore False risponde alla funzione isnull().

In maniera analoga, se vogliamo conservare tutte le colonne che hanno almeno 5 valori non nulli, dobbiamo scrivere:

df.dropna(axis='columns', thresh=5, inplace=True)

Lavorare con sezioni del dataframe: il parametro subset

Abbiamo visto in precedenza che è possibile applicare dropna() ad una sottosezione del dataframe utilizzando il parametro subset. Ricapitolando, possiamo eliminare tutte le righe che contengono almeno un valore nulle in corrispondenza di sole due colonne scrivendo:

df.dropna(axis='index', subset=['Data', 'Codice posizione'], inplace=True)

Per fare il contrario, ovvero eliminare tutte le colonne che contengono almeno un valore nullo in corrispondenza di due righe, possiamo fare come spiegato qui:

df.dropna(axis='columns', subset[0,3], inplace=True)

infatti, con questa riga di codice, andremo ad eliminare le colonne “Data” e “Area” perché contengono dei valori nulli in corrispondenza della riga 3.

 
Immagine 6

Immagine 6

Il parametro inplace

Lo abbiamo già utilizzato e di conseguenza non ci dilungheremo molto. Il parametro inplace serve per applicare una funzione direttamente al dataframe. Il valore di default di inplace corrisponde a False: in questo caso le modifiche apportate dalla funzione non verranno applicate al dataframe.

Andando invece ad impostarlo come True, il dataframe verrà aggiornato in modo da includere le modifiche imposte dalla funzione che stiamo utilizzando, nel nostro caso dropna().

Conclusione

Comprendere il tipo di valori che popolano un dataframe è un’operazione essenziale che deve sempre precedere la manipolazione dei dati.

In alternativa all’approccio osservato in questo articolo, ovvero la rimozione delle colonne/righe che contengono valori nulli, possiamo scegliere di sostituire questi ultimi con qualcos’altro.