Comment puis-je remplacer toutes les valeurs NaN par des zéros dans une colonne d'une trame de données pandas


458

J'ai une trame de données comme ci-dessous

      itm Date                  Amount 
67    420 2012-09-30 00:00:00   65211
68    421 2012-09-09 00:00:00   29424
69    421 2012-09-16 00:00:00   29877
70    421 2012-09-23 00:00:00   30990
71    421 2012-09-30 00:00:00   61303
72    485 2012-09-09 00:00:00   71781
73    485 2012-09-16 00:00:00     NaN
74    485 2012-09-23 00:00:00   11072
75    485 2012-09-30 00:00:00  113702
76    489 2012-09-09 00:00:00   64731
77    489 2012-09-16 00:00:00     NaN

lorsque j'essaie d'appliquer une fonction à la colonne Montant, j'obtiens l'erreur suivante.

ValueError: cannot convert float NaN to integer

J'ai essayé d'appliquer une fonction en utilisant .isnan du module mathématique J'ai essayé l'attribut pandas .replace J'ai essayé l'attribut de données .sparse de pandas 0.9 J'ai également essayé si l'instruction NaN == NaN dans une fonction. J'ai également consulté cet article Comment remplacer les valeurs NA par des zéros dans une trame de données R? tout en regardant d'autres articles. Toutes les méthodes que j'ai essayées n'ont pas fonctionné ou ne reconnaissent pas NaN. Tous les conseils ou solutions seraient appréciés.


Le seul problème est que df.fill.na () ne fonctionne pas si le bloc de données sur lequel vous l'appliquez est rééchantillonné ou a été découpé via la fonction loc
Prince Agarwal

Réponses:


754

Je crois DataFrame.fillna()que cela fera pour vous.

Lien vers Docs pour une trame de données et pour une série .

Exemple:

In [7]: df
Out[7]: 
          0         1
0       NaN       NaN
1 -0.494375  0.570994
2       NaN       NaN
3  1.876360 -0.229738
4       NaN       NaN

In [8]: df.fillna(0)
Out[8]: 
          0         1
0  0.000000  0.000000
1 -0.494375  0.570994
2  0.000000  0.000000
3  1.876360 -0.229738
4  0.000000  0.000000

Pour remplir les NaN dans une seule colonne, sélectionnez uniquement cette colonne. dans ce cas, j'utilise inplace = True pour réellement changer le contenu de df.

In [12]: df[1].fillna(0, inplace=True)
Out[12]: 
0    0.000000
1    0.570994
2    0.000000
3   -0.229738
4    0.000000
Name: 1

In [13]: df
Out[13]: 
          0         1
0       NaN  0.000000
1 -0.494375  0.570994
2       NaN  0.000000
3  1.876360 -0.229738
4       NaN  0.000000

ÉDITER:

Pour éviter cela SettingWithCopyWarning, utilisez la fonctionnalité spécifique aux colonnes intégrée:

df.fillna({1:0}, inplace=True)

1
Est-il garanti qu'il df[1]s'agit d'une vue plutôt que d'une copie du DF d'origine? De toute évidence, s'il y a une situation rare où il s'agit d'une copie, cela provoquerait un bogue super gênant. Y a-t-il une déclaration claire à ce sujet dans la documentation des pandas?
max

@max Voir ceci, pourrait répondre à votre question: stackoverflow.com/questions/23296282/…
Aman

Merci. Ma compréhension est-elle correcte dans cette réponse, un "indexeur qui définit" est l'opération d'indexation la plus externe (exécutée juste avant l'affectation. Donc, toute affectation qui n'utilise qu'un seul indexeur est garantie comme étant sûre, ce qui rend votre code sûr?
max


1
le dernier exemple lance un SettingWithCopyWarning
Sip

124

Il n'est pas garanti que le découpage renvoie une vue ou une copie. Tu peux faire

df['column'] = df['column'].fillna(value)

14
Je viens de découvrir le problème "inplace = True". Cette réponse évite le problème et je pense que c'est la solution la plus propre présentée.
TimCera

48

Vous pouvez utiliser replacepour passer NaNà 0:

import pandas as pd
import numpy as np

# for column
df['column'] = df['column'].replace(np.nan, 0)

# for whole dataframe
df = df.replace(np.nan, 0)

# inplace
df.replace(np.nan, 0, inplace=True)

Va-t-il seulement remplacer NaN? ou il remplacera également la valeur où NAou NaNcomme df.fillna(0)? Je cherche une solution qui ne remplace que la valeur là où il y en a NaNet nonNA
Shyam Bhimani

1
@ShyamBhimani, il ne devrait remplacer que les NaNvaleurs ie, où np.isnanest True
Anton Protopopov

23

Je voulais juste fournir un peu de mise à jour / cas spécial car il semble que les gens viennent toujours ici. Si vous utilisez un multi-index ou utilisez un index-slicer, l'option inplace = True peut ne pas être suffisante pour mettre à jour la tranche que vous avez choisie. Par exemple, dans un multi-index de niveau 2x2, cela ne changera aucune valeur (à partir de pandas 0.15):

idx = pd.IndexSlice
df.loc[idx[:,mask_1],idx[mask_2,:]].fillna(value=0,inplace=True)

Le "problème" est que le chaînage rompt la capacité fillna de mettre à jour la trame de données d'origine. J'ai mis "problème" entre guillemets car il y a de bonnes raisons pour les décisions de conception qui ont conduit à ne pas interpréter à travers ces chaînes dans certaines situations. En outre, c'est un exemple complexe (bien que j'y ai vraiment rencontré), mais la même chose peut s'appliquer à moins de niveaux d'index selon la façon dont vous découpez.

La solution est DataFrame.update:

df.update(df.loc[idx[:,mask_1],idx[[mask_2],:]].fillna(value=0))

C'est une ligne, se lit raisonnablement bien (en quelque sorte) et élimine tout problème inutile avec des variables ou des boucles intermédiaires tout en vous permettant d'appliquer fillna à n'importe quelle tranche à plusieurs niveaux que vous aimez!

Si quelqu'un peut trouver des endroits où cela ne fonctionne pas, veuillez poster dans les commentaires, je l'ai dérangé et j'ai regardé la source et cela semble résoudre au moins mes problèmes de tranche multi-index.


21

Le code ci-dessous a fonctionné pour moi.

import pandas

df = pandas.read_csv('somefile.txt')

df = df.fillna(0)

7

Un moyen facile de remplir les valeurs manquantes: -

remplissage des colonnes de chaînes: lorsque les colonnes de chaînes ont des valeurs manquantes et des valeurs NaN.

df['string column name'].fillna(df['string column name'].mode().values[0], inplace = True)

remplissage des colonnes numériques: lorsque les colonnes numériques ont des valeurs manquantes et des valeurs NaN.

df['numeric column name'].fillna(df['numeric column name'].mean(), inplace = True)

remplir NaN avec zéro:

df['column name'].fillna(0, inplace = True)

5

Vous pouvez également utiliser des dictionnaires pour remplir les valeurs NaN des colonnes spécifiques dans le DataFrame plutôt que de remplir tous les DF avec un oneValue.

import pandas as pd

df = pd.read_excel('example.xlsx')
df.fillna( {
        'column1': 'Write your values here',
        'column2': 'Write your values here',
        'column3': 'Write your values here',
        'column4': 'Write your values here',
        .
        .
        .
        'column-n': 'Write your values here'} , inplace=True)

Il s'agit de la solution destinée aux développeurs à la question du PO.
johnDanger

4

entrez la description de l'image ici

Considérant que la colonne particulière Amountdans le tableau ci-dessus est de type entier. Voici une solution:

df['Amount'] = df.Amount.fillna(0).astype(int)

De même, vous pouvez le remplir avec différents types de données comme float, stretc.

En particulier, je considérerais le type de données pour comparer différentes valeurs de la même colonne.


2

Pour remplacer les valeurs na dans les pandas

df['column_name'].fillna(value_to_be_replaced,inplace=True)

si inplace = False, au lieu de mettre à jour le df (dataframe), il retournera les valeurs modifiées.


1

Si vous deviez le convertir en une trame de données pandas, vous pouvez également le faire en utilisant fillna.

import numpy as np
df=np.array([[1,2,3, np.nan]])

import pandas as pd
df=pd.DataFrame(df)
df.fillna(0)

Cela renverra les éléments suivants:

     0    1    2   3
0  1.0  2.0  3.0 NaN
>>> df.fillna(0)
     0    1    2    3
0  1.0  2.0  3.0  0.0

1

Il existe principalement deux options; en cas d'imputation ou de remplissage de valeurs manquantes NaN / np.nan avec seulement des remplacements numériques (sur la ou les colonnes):

df['Amount'].fillna(value=None, method= ,axis=1,) est suffisant:

De la documentation:

valeur: scalaire, dict, série ou DataFrame Valeur à utiliser pour remplir les trous (par exemple 0), alternativement un dict / Series / DataFrame de valeurs spécifiant la valeur à utiliser pour chaque index (pour une série) ou colonne (pour un DataFrame) . (les valeurs ne figurant pas dans le dict / Series / DataFrame ne seront pas remplies). Cette valeur ne peut pas être une liste.

Ce qui signifie que les «chaînes» ou les «constantes» ne peuvent plus être imputées.

Pour des imputations plus spécialisées, utilisez SimpleImputer () :

from sklearn.impute import SimpleImputer
si = SimpleImputer(strategy='constant', missing_values=np.nan, fill_value='Replacement_Value')
df[['Col-1', 'Col-2']] = si.fit_transform(X=df[['C-1', 'C-2']])

0

Pour remplacer nan dans différentes colonnes de différentes manières:

   replacement= {'column_A': 0, 'column_B': -999, 'column_C': -99999}
   df.fillna(value=replacement)
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.