296 votes

pandas DataFrame : remplacer les valeurs nan par la moyenne des colonnes

J'ai un DataFrame pandas rempli principalement de nombres réels, mais il y a quelques nan dans ce domaine également.

Comment remplacer le nan avec les moyennes des colonnes où ils se trouvent ?

Cette question est très similaire à celle-ci : numpy array : remplacer les valeurs nan par la moyenne des colonnes mais, malheureusement, la solution donnée ne fonctionne pas pour un DataFrame pandas.

403voto

bmu Points 7109

Vous pouvez simplement utiliser DataFrame.fillna pour remplir le nan directement :

In [27]: df 
Out[27]: 
          A         B         C
0 -0.166919  0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3       NaN -2.027325  1.533582
4       NaN       NaN  0.461821
5 -0.788073       NaN       NaN
6 -0.916080 -0.612343       NaN
7 -0.887858  1.033826       NaN
8  1.948430  1.025011 -2.982224
9  0.019698 -0.795876 -0.046431

In [28]: df.mean()
Out[28]: 
A   -0.151121
B   -0.231291
C   -0.530307
dtype: float64

In [29]: df.fillna(df.mean())
Out[29]: 
          A         B         C
0 -0.166919  0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3 -0.151121 -2.027325  1.533582
4 -0.151121 -0.231291  0.461821
5 -0.788073 -0.231291 -0.530307
6 -0.916080 -0.612343 -0.530307
7 -0.887858  1.033826 -0.530307
8  1.948430  1.025011 -2.982224
9  0.019698 -0.795876 -0.046431

La docstring de fillna dit que value devrait être un scalaire ou un dict, cependant, il semble fonctionner avec un Series également. Si vous voulez passer un dict, vous pouvez utiliser df.mean().to_dict() .

98voto

Ammar Shigri Points 891

Essayez :

sub2['income'].fillna((sub2['income'].mean()), inplace=True)

46voto

Gaurav Singh Points 419

Le code ci-dessous fait le travail, MAIS ses performances en pâtissent, car il s'agit d'un DataFrame avec des # enregistrements de 100k ou plus :

df.fillna(df.mean())

D'après mon expérience, il convient de remplacer les valeurs NaN (que ce soit par la moyenne ou la médiane), uniquement là où c'est nécessaire, plutôt que d'appliquer fillna() à l'ensemble du DataFrame .

J'avais un DataFrame avec 20 variables, et seulement 4 d'entre elles nécessitaient le traitement de valeurs NaN (remplacement). J'ai essayé le code ci-dessus (code 1), ainsi qu'une version légèrement modifiée de celui-ci (code 2), où je l'ai exécuté de manière sélective, c'est-à-dire uniquement sur les variables qui avaient une valeur NaN.

#------------------------------------------------
#----(Code 1) Treatment on overall DataFrame-----

df.fillna(df.mean())

#------------------------------------------------
#----(Code 2) Selective Treatment----------------

for i in df.columns[df.isnull().any(axis=0)]:     #---Applying Only on variables with NaN values
    df[i].fillna(df[i].mean(),inplace=True)

#---df.isnull().any(axis=0) gives True/False flag (Boolean value series), 
#---which when applied on df.columns[], helps identify variables with NaN values

Voici les performances que j'ai observées lorsque j'ai continué à augmenter le nombre d'enregistrements dans le DataFrame.

DataFrame avec ~100k enregistrements

  • Code 1 : 22,06 secondes
  • Code 2 : 0,03 seconde

DataFrame avec ~200k enregistrements

  • Code 1 : 180,06 secondes
  • Code 2 : 0,06 seconde

DataFrame avec ~1.6 Million d'enregistrements

  • Code 1 : le code s'exécute sans fin
  • Code 2 : 0,40 seconde

DataFrame avec ~13 millions d'enregistrements

  • Code 1 : --n'a même pas essayé, après avoir vu les performances sur 1,6 millions d'enregistrements--.
  • Code 2 : 3,20 secondes

Toutes mes excuses pour cette longue réponse ! J'espère que cela vous aidera !

42voto

Jeff Points 27612
In [16]: df = DataFrame(np.random.randn(10,3))

In [17]: df.iloc[3:5,0] = np.nan

In [18]: df.iloc[4:6,1] = np.nan

In [19]: df.iloc[5:8,2] = np.nan

In [20]: df
Out[20]: 
          0         1         2
0  1.148272  0.227366 -2.368136
1 -0.820823  1.071471 -0.784713
2  0.157913  0.602857  0.665034
3       NaN -0.985188 -0.324136
4       NaN       NaN  0.238512
5  0.769657       NaN       NaN
6  0.141951  0.326064       NaN
7 -1.694475 -0.523440       NaN
8  0.352556 -0.551487 -1.639298
9 -2.067324 -0.492617 -1.675794

In [22]: df.mean()
Out[22]: 
0   -0.251534
1   -0.040622
2   -0.841219
dtype: float64

Appliquer par colonne la moyenne de ces colonnes et remplir

In [23]: df.apply(lambda x: x.fillna(x.mean()),axis=0)
Out[23]: 
          0         1         2
0  1.148272  0.227366 -2.368136
1 -0.820823  1.071471 -0.784713
2  0.157913  0.602857  0.665034
3 -0.251534 -0.985188 -0.324136
4 -0.251534 -0.040622  0.238512
5  0.769657 -0.040622 -0.841219
6  0.141951  0.326064 -0.841219
7 -1.694475 -0.523440 -0.841219
8  0.352556 -0.551487 -1.639298
9 -2.067324 -0.492617 -1.675794

16voto

Pranay Aryal Points 2298

Si vous voulez imputer les valeurs manquantes avec la moyenne et que vous voulez aller colonne par colonne, alors cela n'imputera que la moyenne de cette colonne. Cela pourrait être un peu plus lisible.

sub2['income'] = sub2['income'].fillna((sub2['income'].mean()))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X