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


177

J'ai un DataFrame pandas rempli principalement de nombres réels, mais il contient également quelques nanvaleurs.

Comment puis-je remplacer les nans par des moyennes de colonnes là où elles se trouvent?

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

Réponses:


273

Vous pouvez simplement utiliser DataFrame.fillnapour remplir les nan's 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 fillnadit que cela valuedevrait être un scalaire ou un dict, mais il semble également fonctionner avec un Series. Si vous voulez passer un dict, vous pouvez utiliser df.mean().to_dict().


10
df.fillna(df.mean())renverra le nouveau dataframe, vous devrez donc écrire df=df.fillna(df.mean())pour le conserver.
yannis

des idées pourquoi je pourrais obtenir le mauvais montant imputé pour la moyenne en utilisant ceci?
bernando_vialli

25
Au lieu de df=df.fillna(df.mean())vous pouvez également utiliserdf.fillna(df.mean(), inplace=True)
Anderson Pimentel

20
ATTENTION: si vous souhaitez l'utiliser pour l'apprentissage automatique / la science des données: du point de vue de la science des données, il est erroné de remplacer d'abord NA, puis de le diviser en train et de tester ... Vous DEVEZ d'abord vous diviser en train et tester, puis remplacer NA par signifie en train, puis appliquez ce modèle de prétraitement avec état pour tester, voir la réponse impliquant sklearn ci-dessous!
Fabian Werner

2
@ amalik2205 car sinon, vous perdez des informations de l'ensemble de test vers l'ensemble d'entraînement! Imaginez-le comme ceci: nous avons 100 lignes de données et nous considérons la colonne x. Les 99 premières entrées de x sont NA. Nous voulons diviser la ligne 100 en tant qu'ensemble de test. Supposons que la ligne 100 a la valeur 20 dans la colonne x. Ensuite, vous remplacerez toutes les entrées de l'ensemble d'entraînement dans la colonne x par 20, une valeur provenant à 100% de l'ensemble de test. Par conséquent, l'évaluation pourrait vous tromper!
Fabian Werner


28
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

5
Je ne sais pas pourquoi, mais df.fillna (df.mean ()) n'a pas fonctionné, seule votre version avec apply. Python 3
Rocketq

12
# To read data from csv file
Dataset = pd.read_csv('Data.csv')

X = Dataset.iloc[:, :-1].values

# To calculate mean use imputer class
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
imputer = imputer.fit(X[:, 1:3])
X[:, 1:3] = imputer.transform(X[:, 1:3])

Quel est l'avantage de tout cela par rapport aux alternatives beaucoup plus simples?
AMC

@Roshan Jha Il vaut toujours mieux expliquer la logique. Il existe de nombreuses façons de réaliser la même tâche dans R & Python. Cependant, si vous suggérez quelque chose de différent, vous voudrez peut-être souligner certains avantages de le faire
Dr Nisha Arora

10

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

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

3
Veuillez expliquer comment cela résout le problème.
Gurwinder Singh

10

Utilisez directement df.fillna(df.mean())pour remplir toute la valeur nulle avec la moyenne

Si vous voulez remplir une valeur nulle avec la moyenne de cette colonne, vous pouvez utiliser ceci

supposons que x=df['Item_Weight']voici le Item_Weightnom de la colonne

ici nous assignons (remplissez les valeurs nulles de x avec la moyenne de x dans x)

df['Item_Weight'] = df['Item_Weight'].fillna((df['Item_Weight'].mean()))

Si vous souhaitez remplir une valeur nulle avec une chaîne, utilisez

voici le Outlet_sizenom de la colonne

df.Outlet_Size = df.Outlet_Size.fillna('Missing')

9

Une autre option en plus de celles ci-dessus est:

df = df.groupby(df.columns, axis = 1).transform(lambda x: x.fillna(x.mean()))

C'est moins élégant que les réponses précédentes pour la moyenne, mais cela pourrait être plus court si vous souhaitez remplacer les valeurs nulles par une autre fonction de colonne.


7

Pandas: Comment remplacer les nanvaleurs NaN ( ) par la moyenne (moyenne), la médiane ou d'autres statistiques d'une colonne

Disons que votre DataFrame est dfet que vous avez une colonne appelée nr_items. C'est: df['nr_items']

Si vous souhaitez remplacer les NaNvaleurs de votre colonne df['nr_items']par la moyenne de la colonne :

Utilisez la méthode .fillna():

mean_value=df['nr_items'].mean()
df['nr_item_ave']=df['nr_items'].fillna(mean_value)

J'ai créé une nouvelle dfcolonne appelée nr_item_avepour stocker la nouvelle colonne avec les NaNvaleurs remplacées par la meanvaleur de la colonne.

Vous devez être prudent lorsque vous utilisez le mean. Si vous avez des valeurs aberrantes, il est plus recommandé d'utiliser lemedian


0

utilisation de la classe de prétraitement de la bibliothèque sklearn

from sklearn.impute import SimpleImputer
missingvalues = SimpleImputer(missing_values = np.nan, strategy = 'mean', axis = 0)
missingvalues = missingvalues.fit(x[:,1:3])
x[:,1:3] = missingvalues.transform(x[:,1:3])

Remarque: dans la version récente, la missing_valuesvaleur du paramètre passe à np.nandeNaN

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.