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.
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
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
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
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.
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.
Utilisez: df.fillna(0)
remplir NaN avec 0.