Skip to content

pandas: Sostituire i valori mancanti (NaN) con fillna()

Python

Puoi sostituire il valore mancante (NaN) in pandas.DataFrame e Series con valore utilizzando il metodo fillna().

In questo articolo vengono descritti i seguenti contenuti.

  • Sostituisci tutti i valori mancanti con lo stesso valore
  • Sostituisci i valori mancanti con valori diversi per ogni colonna
  • Sostituisci i valori mancanti con media, mediana, moda, ecc. per ogni colonna
  • Sostituisci i valori mancanti con valori validi precedenti/successivi:method, limit
  • Operare sul posto:inplace
  • Per panda.Serie

Utilizzare interpolate() se si desidera compilare i valori mancanti con l’interpolazione lineare o spline.

Per ulteriori informazioni sulla rimozione o sul conteggio dei valori mancanti, vedere gli articoli seguenti.

Nota che non solo NaN (Not a Number) ma anche None viene trattato come un valore mancante nei panda.

Ad esempio, leggi un file CSV con valori mancanti con read_csv().

import pandas as pd

df = pd.read_csv('data/src/sample_pandas_normal_nan.csv')
print(df)
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1      NaN   NaN   NaN    NaN    NaN
# 2  Charlie   NaN    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen   NaN    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

Sostituisci tutti i valori mancanti con lo stesso valore

Specificando valore scalare come valore del primo argomento di fillna(), tutti i valori mancanti vengono sostituiti con il valore.

print(df.fillna(0))
#       name   age state  point  other
# 0    Alice  24.0    NY    0.0    0.0
# 1        0   0.0     0    0.0    0.0
# 2  Charlie   0.0    CA    0.0    0.0
# 3     Dave  68.0    TX   70.0    0.0
# 4    Ellen   0.0    CA   88.0    0.0
# 5    Frank  30.0     0    0.0    0.0

Si noti che il tipo di dati dtype di una colonna di numeri che include NaN è float, quindi anche se si sostituisce NaN con un numero intero, il tipo di dati rimane float. Se vuoi convertirlo in int, usa astype().

Sostituisci i valori mancanti con valori diversi per ogni colonna

Specificando un dizionario dict come primo valore di argomento di fillna(), puoi assegnare valori diversi per ciascuna colonna.

Specifica un dizionario di {nome_colonna: valore}. Se non viene specificato il nome di una colonna, i valori mancanti nella relativa colonna vengono mantenuti (= non sostituito). Se la chiave non corrisponde al nome di una colonna, viene ignorata.

print(df.fillna({'name': 'XXX', 'age': 20, 'ZZZ': 100}))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1      XXX  20.0   NaN    NaN    NaN
# 2  Charlie  20.0    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  20.0    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

Puoi anche specificare pandas.Series. Le etichette di pandas.Series coerente alla chiave di dict.

s_for_fill = pd.Series(['XXX', 20, 100], index=['name', 'age', 'ZZZ'])
print(s_for_fill)
# name    XXX
# age      20
# ZZZ     100
# dtype: object

print(df.fillna(s_for_fill))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1      XXX  20.0   NaN    NaN    NaN
# 2  Charlie  20.0    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  20.0    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

La media di ciascuna colonna può essere calcolata con il metodo mean(). pandas.Series viene restituito. NaN è escluso, ma il risultato per una colonna in cui tutti gli elementi sono NaN è NaN.

print(df.mean())
# age      40.666667
# point    79.000000
# other          NaN
# dtype: float64

Se specifichi questo pandas.Series come primo valore di argomento di fillna(), valori mancanti della colonna corrispondenti vengono sostituiti con il valore medio.

print(df.fillna(df.mean()))
#       name        age state  point  other
# 0    Alice  24.000000    NY   79.0    NaN
# 1      NaN  40.666667   NaN   79.0    NaN
# 2  Charlie  40.666667    CA   79.0    NaN
# 3     Dave  68.000000    TX   70.0    NaN
# 4    Ellen  40.666667    CA   88.0    NaN
# 5    Frank  30.000000   NaN   79.0    NaN

Allo stesso modo, se vuoi sostituire i valori mancanti con la mediana, usa il metodo median(). Se il numero di elementi è pari, viene restituita la media dei due valori mediani.

print(df.fillna(df.median()))
#       name   age state  point  other
# 0    Alice  24.0    NY   79.0    NaN
# 1      NaN  30.0   NaN   79.0    NaN
# 2  Charlie  30.0    CA   79.0    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  30.0    CA   88.0    NaN
# 5    Frank  30.0   NaN   79.0    NaN

La modalità può essere ottenuta con il metodo mode(). Poiché mode() restituisce pandas.DataFrame, la prima riga viene recuperata come pandas.Series da iloc[0] in questo esempio.

print(df.fillna(df.mode().iloc[0]))
#       name   age state  point  other
# 0    Alice  24.0    NY   70.0    NaN
# 1    Alice  24.0    CA   70.0    NaN
# 2  Charlie  24.0    CA   70.0    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  24.0    CA   88.0    NaN
# 5    Frank  30.0    CA   70.0    NaN

In questi esempi, non ci sono problemi, ma metodi come mean() possono restituire valori imprevisti perché tentano di utilizzare non solo colonne numeriche ma anche altri tipi di colonne per la configurazione predefinita.

In mean() e così via, se l’argomento numeric_only è impostato su True, vengono elaborati solo le colonne numeriche. Si noti che le colonne di tipo bool vengono trattate come True=1 e False=0 anche se numeric_only=True.

Sostituisci i valori mancanti con valori validi precedenti/successivi:method, limit

L’argomento del metodo di fillna() può essere utilizzato per sostituire i valori mancanti con valori validi precedenti/successivi.

Se metodo è impostato su ‘fill’ o ‘pad’, i valori mancanti vengono sostituiti con valori validi precedenti (= riempimento in avanti) e se ‘bfill’ o ‘backfill’, sostituito con i valori validi successivi (= riempimento all’ indietro).

print(df.fillna(method='ffill'))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1    Alice  24.0    NY    NaN    NaN
# 2  Charlie  24.0    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  68.0    CA   88.0    NaN
# 5    Frank  30.0    CA   88.0    NaN

print(df.fillna(method='bfill'))
#       name   age state  point  other
# 0    Alice  24.0    NY   70.0    NaN
# 1  Charlie  68.0    CA   70.0    NaN
# 2  Charlie  68.0    CA   70.0    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  30.0    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

Se viene specificato il metodo, limite può essere utilizzato per specificare il numero massimo di sostituzioni consecutive.

print(df.fillna(method='ffill', limit=1))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1    Alice  24.0    NY    NaN    NaN
# 2  Charlie   NaN    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  68.0    CA   88.0    NaN
# 5    Frank  30.0    CA   88.0    NaN

print(df.fillna(method='bfill', limit=1))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1  Charlie   NaN    CA    NaN    NaN
# 2  Charlie  68.0    CA   70.0    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  30.0    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

Potrebbe non essere usato spesso, ma se l’argomento dell’asse è impostato su 1 o ‘colonne’, i valori mancanti vengono sostituiti con i valori sinistro e destro.

print(df.fillna(method='ffill', axis=1))
#       name      age state point other
# 0    Alice     24.0    NY    NY    NY
# 1      NaN      NaN   NaN   NaN   NaN
# 2  Charlie  Charlie    CA    CA    CA
# 3     Dave     68.0    TX  70.0  70.0
# 4    Ellen    Ellen    CA  88.0  88.0
# 5    Frank     30.0  30.0  30.0  30.0

print(df.fillna(method='bfill', axis=1))
#       name   age state point other
# 0    Alice  24.0    NY   NaN   NaN
# 1      NaN   NaN   NaN   NaN   NaN
# 2  Charlie    CA    CA   NaN   NaN
# 3     Dave  68.0    TX  70.0   NaN
# 4    Ellen    CA    CA  88.0   NaN
# 5    Frank  30.0   NaN   NaN   NaN

I metodi che vengono eseguiti all’argomento del metodo fornito separatamente.

ffill() e pad() sono equivalenti a fillna(method=’ffill’), e bfill() e backfill() sono equivalenti a fillna(method=’bfill’). È possibile specificare il limite.

print(df.ffill())
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1    Alice  24.0    NY    NaN    NaN
# 2  Charlie  24.0    CA    NaN    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  68.0    CA   88.0    NaN
# 5    Frank  30.0    CA   88.0    NaN

print(df.bfill(limit=1))
#       name   age state  point  other
# 0    Alice  24.0    NY    NaN    NaN
# 1  Charlie   NaN    CA    NaN    NaN
# 2  Charlie  68.0    CA   70.0    NaN
# 3     Dave  68.0    TX   70.0    NaN
# 4    Ellen  30.0    CA   88.0    NaN
# 5    Frank  30.0   NaN    NaN    NaN

Operare sul posto:inplace

Come mostrato negli esempi precedenti, per viene visualizzato come predefinito, viene restituito un nuovo oggetto l’oggetto originale non modificato, ma se inplace=True, l’oggetto originale stesso viene aggiornato.

df.fillna(0, inplace=True)
print(df)
#       name   age state  point  other
# 0    Alice  24.0    NY    0.0    0.0
# 1        0   0.0     0    0.0    0.0
# 2  Charlie   0.0    CA    0.0    0.0
# 3     Dave  68.0    TX   70.0    0.0
# 4    Ellen   0.0    CA   88.0    0.0
# 5    Frank  30.0     0    0.0    0.0

Per panda.Serie

Puoi anche usare fillna() da pandas.Series come negli esempi precedenti di pandas.DataFrame.

s = pd.read_csv('data/src/sample_pandas_normal_nan.csv')['age']
print(s)
# 0    24.0
# 1     NaN
# 2     NaN
# 3    68.0
# 4     NaN
# 5    30.0
# Name: age, dtype: float64

print(s.fillna(100))
# 0     24.0
# 1    100.0
# 2    100.0
# 3     68.0
# 4    100.0
# 5     30.0
# Name: age, dtype: float64

print(s.fillna({1: 100, 4: -100}))
# 0     24.0
# 1    100.0
# 2      NaN
# 3     68.0
# 4   -100.0
# 5     30.0
# Name: age, dtype: float64

print(s.fillna(method='bfill', limit=1))
# 0    24.0
# 1     NaN
# 2    68.0
# 3    68.0
# 4    30.0
# 5    30.0
# Name: age, dtype: float64

Viene fornito anche i metodi che contengono all’argomento del metodo.

print(s.bfill(limit=1))
# 0    24.0
# 1     NaN
# 2    68.0
# 3    68.0
# 4    30.0
# 5    30.0
# Name: age, dtype: float64