291 votes

Pandas dataframe fillna() seulement quelques colonnes en place

J'essaie de remplir les valeurs nulles d'un cadre de données Pandas avec des 0 pour seulement un sous-ensemble de colonnes.

Quand je le fais :

import pandas as pd
df = pd.DataFrame(data={'a':[1,2,3,None],'b':[4,5,None,6],'c':[None,None,7,8]})
print df
df.fillna(value=0, inplace=True)
print df

Le résultat :

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  NaN  7.0
3  NaN  6.0  8.0
     a    b    c
0  1.0  4.0  0.0
1  2.0  5.0  0.0
2  3.0  0.0  7.0
3  0.0  6.0  8.0

Il remplace chaque None avec 0 's. Ce que je veux faire, c'est remplacer seulement None dans les colonnes a et b mais pas c .

Quelle est la meilleure façon de procéder ?

428voto

root Points 15363

Vous pouvez sélectionner les colonnes de votre choix et procéder par affectation :

df[['a', 'b']] = df[['a','b']].fillna(value=0)

Le résultat est conforme aux attentes :

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

3 votes

Oui, c'est exactement ce que je veux ! Merci. Y a-t-il un moyen de faire cela en place ? Mon cadre de données d'origine est assez grand.

3 votes

Je ne pense pas qu'il y ait un gain de performance en faisant cela en place puisque vous écrasez le df original de toute façon.

7 votes

Le loc est superflu ici, df[['a', 'b']] = df[['a','b']].fillna(value=0) fonctionnera toujours

208voto

W-B Points 94428

Vous pouvez utiliser dict , fillna avec une valeur différente pour chaque colonne

df.fillna({'a':0,'b':0})
Out[829]: 
     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

Après l'avoir assigné de nouveau

df=df.fillna({'a':0,'b':0})
df
Out[831]: 
     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

2 votes

Vraiment cool, Btw pour la dictée vous pouvez utiliser fromkeys si vous voulez, +1

1 votes

La réponse/l'exemple serait plus clair s'il montrait réellement des valeurs différentes pour les différentes colonnes.

0 votes

@RufusVS c'est vrai, mais essayez toujours de correspondre à la sortie attendue de l'op.

58voto

Leesa H. Points 71

Vous pouvez éviter de faire une copie de l'objet en utilisant la solution de Wen et inplace=True :

df.fillna({'a':0, 'b':0}, inplace=True)
print(df)

Ce qui donne :

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

7 votes

Bien que cela soit correct, éviter une copie n'est pas nécessairement meilleur .

9voto

Josephine M. Ho Points 89

Voici comment vous pouvez faire tout cela en une seule ligne :

df[['a', 'b']].fillna(value=0, inplace=True)

Décomposition : df[['a', 'b']] sélectionne les colonnes pour lesquelles vous voulez remplir des valeurs NaN, value=0 lui indique de remplir les NaNs avec zéro, et inplace=True rendra les changements permanents, sans avoir à faire une copie de l'objet.

6 votes

D'une manière ou d'une autre, cela donne lieu à SettingWithCopyWarning et le changement n'est pas reflété dans df .

5voto

U9-Forward Points 8640

Ou quelque chose comme :

df.loc[df['a'].isnull(),'a']=0
df.loc[df['b'].isnull(),'b']=0

et s'il y a plus :

for i in your_list:
    df.loc[df[i].isnull(),i]=0

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