2016-05-31 20 views
8

Ho un dataframe con 71 colonne e 30597 righe. Voglio sostituire tutte le voci non nanometriche con 1 e i valori nan con 0.Come sostituire tutte le voci non NaN di un dataframe con 1 e tutte le NaN con 0

Inizialmente ho provato il ciclo per ogni valore del dataframe che richiedeva troppo tempo.

Poi usato data_new = data.subtract (dati) che doveva sottrarre tutti i valori della dataframe a se stesso in modo che possa rendere tutti i valori non nulli 0. Ma è verificato un errore come dataframe aveva più voci di stringa.

+0

Possibile duplicato di [Come posso sostituire tutti i valori NaN con Zero in una colonna di un dataframe panda] (http://stackoverflow.com/questions/13295735/how-can-i-replace-all-the- nan-valori-con-zeri-in-una-colonna-di-un-pandas-datafra) –

risposta

4

Usa notnull con colata booleano per int da astype:

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

Esempio:

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

si può prendere il valore di ritorno di df.notnull(), che è False dove il dataframe contiene NaN e True altrimenti e lanciarlo su intero, dandoti il ​​0 dove DataFrame è NaN e 1 altrimenti:

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

Se davvero si vuole scrivere nel vostro dataframe originale, questo funzionerà:

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

Siamo spiacenti, per favore non copi la mia risposta. Penso che la tua versione sia uguale alla mia, quindi penso che non sia necessario. – jezrael

+1

Hai notato che ho postato questa risposta prima di te? – fmarc

+0

Sì, ma non con 'notnull()'. La tua risposta era con '~ isnull()'. Ed è uguale, quindi penso che la tua soluzione sia buona come la mia. – jezrael

0

C'è un metodo .fillna() su DataFrames che fa quello che vi serve. Per esempio:

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

o

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

vorrei consigliare fare una nuova colonna piuttosto che sostituire. È sempre possibile eliminare la colonna precedente, se necessario, ma è sempre utile disporre di un'origine per una colonna popolata tramite un'operazione su un'altra.

ad es. se df [ 'col1'] è la colonna esistente

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

dove col2 è la nuova colonna. Dovrebbe funzionare anche se col2 ha delle stringhe.

0

Usa: df.fillna(0)

per riempire NaN con 0.

2

faccio un sacco di analisi dei dati e sono interessati a trovare nuovi/metodi più veloci di effettuare operazioni. Non avevo mai incontrato il metodo di jezrael, quindi ero curioso di confrontarlo con il mio solito metodo (cioè sostituire con l'indicizzazione). NOTA: Questa non è una risposta alla domanda dell'OP, piuttosto è un'illustrazione dell'efficienza del metodo di jezrael. Dal momento che questa NON è una risposta, rimuoverò questo post se la gente non lo troverà utile (e dopo essere stato downvoted nell'oblio!). Lascia un commento se pensi che dovrei rimuoverlo.

Ho creato un dataframe di dimensioni moderate e ho fatto più sostituzioni utilizzando sia il metodo df.notnull(). Astype (int) che l'indicizzazione semplice (come farei normalmente in questo caso). Si scopre che quest'ultimo è più lento di circa cinque volte. Solo una fyi per chiunque lavori su larga scala.

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) 

Questo produce tempi di 0,142 se 0,685 s rispettivamente. È chiaro chi è il vincitore.

Problemi correlati