Skip to content

pandas : Remplacer les valeurs manquantes (NaN) avec fillna()

Vous pouvez remplacer la valeur manquante (NaN) dans pandas.DataFrame et Series par n’importe quelle valeur à l’aide de la méthode fillna().

Cet article décrit le contenu suivant.

  • Remplacer toutes les valeurs manquantes par la même valeur
  • Remplacer les valeurs manquantes par des valeurs différentes pour chaque colonne
  • Remplacez les valeurs manquantes par la moyenne, la médiane, le mode, etc. pour chaque colonne
  • Remplacez les valeurs manquantes par les valeurs valides précédentes/suivantes :method, limit
  • Opérer sur place :inplace
  • Pour les pandas.Série

Utilisez interpolate() si vous souhaitez remplir les valeurs manquantes avec une interpolation linéaire ou spline.

Pour plus d’informations sur la suppression ou le comptage des valeurs manquantes, consultez les articles suivants.

Notez que non seulement NaN (Not a Number) mais aussi None est traité comme une valeur manquante dans les pandas.

Par exemple, lisez un fichier CSV avec des valeurs manquantes avec 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

Remplacer toutes les valeurs manquantes par la même valeur

En spécifiant la valeur scalaire comme première valeur d’argument de fillna(), toutes les valeurs manquantes sont remplacées par la valeur.

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

Notez que le type de données dtype d’une colonne de nombres incluant NaN est flottant, donc même si vous remplacez NaN par un nombre entier, le type de données reste flottant. Si vous voulez le convertir en int, utilisez astype().

Remplacer les valeurs manquantes par des valeurs différentes pour chaque colonne

En spécifiant un dictionnaire dict comme première valeur d’argument de fillna(), vous pouvez attribuer des valeurs différentes pour chaque colonne.

Spécifiez un dictionnaire de {column_name : valeur}. Si un nom de colonne n’est pas spécifié, les valeurs manquantes dans sa colonne sont conservées (= non remplacées). Si la clé ne correspond pas à un nom de colonne, elle est ignorée.

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

Vous pouvez également spécifier pandas.Series. Les étiquettes de pandas.Series correspondent à la clé de 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 moyenne de chaque colonne peut être calculée avec la méthode mean(). pandas.Series est renvoyé. NaN est exclu, mais le résultat pour une colonne où tous les éléments sont NaN est NaN.

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

Si vous spécifiez ce pandas.Series comme première valeur d’argument de fillna(), les valeurs manquantes de la colonne correspondante sont remplacées par la valeur moyenne.

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

De même, si vous souhaitez remplacer les valeurs manquantes par la médiane, utilisez la méthode median(). Si le nombre d’éléments est pair, la moyenne des deux valeurs médianes est renvoyée.

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

Le mode peut être obtenu avec la méthode mode(). Puisque mode() renvoie pandas.DataFrame, la première ligne est récupérée en tant que pandas.Series par iloc[0] dans cet exemple.

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

Dans ces exemples, il n’y a pas de problème, mais des méthodes telles que mean() peuvent renvoyer des valeurs inattendues car elles tentent de faire fonctionner non seulement des colonnes numériques mais également d’autres types de colonnes par défaut.

Dans mean() et ainsi de suite, si l’argument numeric_only est défini sur True, seules les colonnes numériques sont traitées. Notez que les colonnes de type bool sont traitées comme True=1 et False=0 même si numeric_only=True.

Remplacez les valeurs manquantes par les valeurs valides précédentes/suivantes :method, limit

L’argument de méthode de fillna() peut être utilisé pour remplacer les valeurs manquantes par des valeurs valides précédentes/suivantes.

Si la méthode est définie sur ‘ffill’ ou ‘pad’, les valeurs manquantes sont remplacées par les valeurs valides précédentes (= remplissage vers l’avant), et si ‘bfill’ ou ‘backfill’, remplacées par les valeurs valides suivantes (= remplissage vers l’arrière).

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

Si method est spécifié, limit peut être utilisé pour spécifier le nombre maximum de remplacements consécutifs.

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

Il peut ne pas être utilisé souvent, mais si l’argument de l’axe est défini sur 1 ou ‘columns’, les valeurs manquantes sont remplacées par les valeurs gauche et droite.

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

Les méthodes qui correspondent à l’argument method sont fournies séparément.

ffill() et pad() sont équivalents à fillna(method=’ffill’), et bfill() et backfill() sont équivalents à fillna(method=’bfill’). Vous pouvez spécifier une 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

Opérer sur place :inplace

Comme indiqué dans les exemples ci-dessus, par défaut, un nouvel objet est renvoyé et l’objet d’origine n’est pas modifié, mais si inplace=True, l’objet d’origine lui-même est mis à jour.

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

Pour les pandas.Série

Vous pouvez également utiliser fillna() de pandas.Series comme dans les exemples précédents de 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

Les méthodes qui correspondent à l’argument de la méthode sont également fournies.

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