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.

piokuc
la source

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().

bmu
la source
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
51

Essayer:

sub2['income'].fillna((sub2['income'].mean()), inplace=True)
Ammar Shigri
la source
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
Jeff
la source
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])
Roshan jha
la source
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()))
Pranay Aryal
la source
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')
Sunny Barnwal
la source
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.

guibor
la source
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

rose.slash
la source
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

Shrikant Chaudhari
la source