
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