2014-05-04 23 views
13

Ho un dataframe panda con una colonna di valori reali che voglio Zscore normalizzare:come zscore normalizzare la colonna panda con nans?

>> a 
array([ nan, 0.0767, 0.4383, 0.7866, 0.8091, 0.1954, 0.6307, 
     0.6599, 0.1065, 0.0508]) 
>> df = pandas.DataFrame({"a": a}) 

Il problema è che un singolo valore nan fa tutta la matrice nan:

>> from scipy.stats import zscore 
>> zscore(df["a"]) 
array([ nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]) 

Qual è la modo corretto per applicare zscore (o una funzione equivalente non da scipy) a una colonna di un dataframe panda e far ignorare i valori nan? Mi piacerebbe che fosse stessa dimensione colonna originale con np.nan per i valori che non possono essere normalizzato

modificare: forse la soluzione migliore è quella di utilizzare scipy.stats.nanmean e scipy.stats.nanstd? Non vedo il motivo per cui i gradi di libertà devono essere cambiate per std per questo scopo:

zscore = lambda x: (x - scipy.stats.nanmean(x))/scipy.stats.nanstd(x) 

risposta

17

Bene le pandas' versioni di mean e std sarà portata di mano il Nan quindi si può solo calcolare in questo modo (per ottenere il stessa SciPy Zscore penso è necessario utilizzare ddof = 0 su std):

df['zscore'] = (df.a - df.a.mean())/df.a.std(ddof=0) 
print df 

     a zscore 
0  NaN  NaN 
1 0.0767 -1.148329 
2 0.4383 0.071478 
3 0.7866 1.246419 
4 0.8091 1.322320 
5 0.1954 -0.747912 
6 0.6307 0.720512 
7 0.6599 0.819014 
8 0.1065 -1.047803 
9 0.0508 -1.235699 
+0

Se si desidera ottenere lo z_score su tutti dataframe, si può provare a usare questo: '' 'def z_score (df): ritorno (df-df.mean())/df.std (ddof = 0) '' 'e' '' df.apply (z_score) '' ' –

4

si potrebbe ignorare nans utilizzando isnan.

z = a     # initialise array for zscores 
z[~np.isnan(a)] = zscore(a[~np.isnan(a)]) 
pandas.DataFrame({'a':a,'Zscore':z}) 

    Zscore  a 
0  NaN  NaN 
1 -1.148329 0.0767 
2 0.071478 0.4383 
3 1.246419 0.7866 
4 1.322320 0.8091 
5 -0.747912 0.1954 
6 0.720512 0.6307 
7 0.819014 0.6599 
8 -1.047803 0.1065 
9 -1.235699 0.0508 
+1

Penso che tu abbia bisogno di" z = a.copy() "piuttosto che" z = a ", altrimenti z sta puntando allo stesso array e sovrascrivi gli elementi di a con i loro zscores. – Pont

Problemi correlati