web-dev-qa-db-fra.com

Comment remplacer toutes les entrées non NaN d’une trame de données par 1 et toutes les NaN avec

J'ai un dataframe avec 71 colonnes et 30597 lignes. Je veux remplacer toutes les entrées non-nan par 1 et les valeurs nan par 0.

Au départ, j'ai essayé la boucle for pour chaque valeur de la trame de données, ce qui prenait trop de temps.

Ensuite, j'ai utilisé data_new = data.subtract (data) qui était censé soustraire toutes les valeurs du dataframe à lui-même afin que je puisse faire en sorte que toutes les valeurs non nulles soient 0. dataframe avait plusieurs entrées de chaîne.

11
Anirban De

Vous pouvez prendre la valeur de retour de df.notnull(), qui est False où le DataFrame contient NaN et True sinon et le transtyper en entier, en vous donnant 0 où le DataFrame est NaN et 1 sinon

newdf = df.notnull().astype('int')

Si vous voulez vraiment écrire dans votre DataFrame original, cela fonctionnera:

df.loc[~df.isnull()] = 1  # not nan
df.loc[df.isnull()] = 0   # nan
17
fmarc

Utilisez notnull avec le transtypage booléen à int par astype :

print ((df.notnull()).astype('int'))

Échantillon:

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [np.nan, 4, np.nan], 'b': [1,np.nan,3]})
print (df)
     a    b
0  NaN  1.0
1  4.0  NaN
2  NaN  3.0

print (df.notnull())
       a      b
0  False   True
1   True  False
2  False   True

print ((df.notnull()).astype('int'))
   a  b
0  0  1
1  1  0
2  0  1
9
jezrael

Il existe une méthode .fillna() sur DataFrames qui répond à vos besoins. Par exemple:

df = df.fillna(0)  # Replace all NaN values with zero, returning the modified DataFrame

ou

df.fillna(0, inplace=True)   # Replace all NaN values with zero, updating the DataFrame directly
2
DainDwarf

Je fais beaucoup d'analyse de données et je suis intéressé par la recherche de méthodes nouvelles/plus rapides pour la réalisation des opérations. Je n’avais jamais rencontré la méthode de Jezrael, j’étais donc curieuse de la comparer à ma méthode habituelle (c’est-à-dire remplacer par indexation). NOTE: Ceci n'est pas une réponse à la question du PO mais plutôt une illustration de l'efficacité de la méthode de Jezrael. Comme ce n'est PAS une réponse, je supprimerai ce message si les gens ne le trouvent pas utile (et après avoir été voté dans l'oubli!). Laissez juste un commentaire si vous pensez que je devrais l'enlever.

J'ai créé un cadre de données de taille moyenne et effectué plusieurs remplacements à la fois à l'aide de la méthode df.notnull (). Astype (int) et d'une indexation simple (comme je le ferais normalement). Il s'avère que ce dernier est environ cinq fois plus lent. Juste un FYI pour quiconque fait des remplacements à grande échelle.

from __future__ import division, print_function

import numpy as np
import pandas as pd
import datetime as dt


# create dataframe with randomly place NaN's
data = np.ones( (1e2,1e2) )
data.ravel()[np.random.choice(data.size,data.size/10,replace=False)] = np.nan

df = pd.DataFrame(data=data)

trials = np.arange(100)


d1 = dt.datetime.now()

for r in trials:
    new_df = df.notnull().astype(int)

print( (dt.datetime.now()-d1).total_seconds()/trials.size )


# create a dummy copy of df.  I use a dummy copy here to prevent biasing the 
# time trial with dataframe copies/creations within the upcoming loop
df_dummy = df.copy()

d1 = dt.datetime.now()

for r in trials:
    df_dummy[df.isnull()] = 0
    df_dummy[df.isnull()==False] = 1

print( (dt.datetime.now()-d1).total_seconds()/trials.size )

Cela donne des temps de 0,142 s et 0,685 s respectivement. Il est clair qui est le gagnant.

2
tnknepp

Je conseillerais de faire une nouvelle colonne plutôt que de simplement remplacer. Vous pouvez toujours supprimer la colonne précédente si nécessaire, mais il est toujours utile d'avoir une source pour une colonne renseignée via une opération sur une autre.

par exemple. si df ['col1'] est la colonne existante

df['col2'] = df['col1'].apply(lambda x: 1 if not pd.isnull(x) else np.nan)

où col2 est la nouvelle colonne. Cela devrait également fonctionner si col2 a des entrées de chaîne.

1
tompiler

Utilisez: df.fillna(0)

remplir NaN avec 0.

0
afuc func