2015-08-21 15 views
6

Non riesco a trovare la versione non for-loop di questo. Dite questo è il mio input:Come normalizzare da un'altra riga in un DataFrame panda?

In [94]: df 
Out[94]: 
     N experiment color value value2 
0 145000   0  red 0.30 0.363953 
1 14000   1  red 0.31 0.218978 
2 13000   2  red 0.29 0.948070 
3 15000   0 yellow 0.31 0.620201 
4 1200   1 yellow 0.32 0.567513 
5 1400   2 yellow 0.31 0.318197 
6 40000   0 green 0.29 0.947226 
7 3000   1 green 0.31 0.084243 
8 7000   2 green 0.32 0.961020 

[9 rows x 5 columns] 

L'esperimento 0 è il mio controllo. Ho eseguito questo esperimento per vari colori. Voglio di normalizzare tutte le righe dall'esperimento colore corrispondente 0.

In [104]: df 
Out[104]: 
     N experiment color value value2 scaled_value scaled_value2 
0 145000   0  red 0.30 0.363953  1.000000  1.000000 
1 14000   1  red 0.31 0.218978  1.033333  0.590786 
2 13000   2  red 0.29 0.948070  0.966667  2.604732 
3 15000   0 yellow 0.31 0.620201  1.000000  1.000000 
4 1200   1 yellow 0.32 0.567513  1.032258  0.914220 
5 1400   2 yellow 0.31 0.318197  1.000000  0.512737 
6 40000   0 green 0.29 0.947226  1.000000  1.000000 
7 3000   1 green 0.31 0.084243  1.068966  0.088680 
8 7000   2 green 0.32 0.961020  1.103448  1.014541 

[9 rows x 7 columns] 

Sembra vorrei esigere l'esperimento a zero parametri per la propria colonna per consentire un facile divisione, ma non riesco a ottenere l'impilamento/girevole/concating per funzionare correttamente. L'ho fatto con i cicli for con l'uso di .at e assegnando valori, ma mi sembrava così sbagliato.

I passi successivi sarebbero normalizzante diverse colonne e creando upplower e limiti di errore inferiore di calcolo (N, valore), (N, valore2), (N, other_values) ecc

+0

Guardare in '' MinMaxScaler' di sklearn'; Immaginerei che abbiano ottimizzato le operazioni vettoriali. È anche abbastanza sicuro che tu possa nutrirlo con i dati 'pandas' http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html – Ryan

+0

@Ryan, non è quello per ridimensionare i valori in una singola colonna/array? Quando dico normalizzare, non intendo gli intervalli di vettore (0,1), ma ognuno è diviso per un valore esterno. – physicsmichael

risposta

4

Un modo potrebbe essere quello di utilizzare transform (qui utilizzando idxmin, anche se ci sono molte alternative) per ottenere gli indici delle righe che vogliamo utilizzare come denominatore:

>>> ii = df.groupby("color")["experiment"].transform("idxmin") 
>>> cols = ["value", "value2"] 
>>> new_cols = (df.loc[:,cols] /df.loc[ii, cols].values) 
>>> df.join(new_cols.rename(columns=lambda x: "scaled_" + x)) 
     N experiment color value value2 scaled_value scaled_value2 
0 145000   0  red 0.30 0.363953  1.000000  1.000000 
1 14000   1  red 0.31 0.218978  1.033333  0.601666 
2 13000   2  red 0.29 0.948070  0.966667  2.604924 
3 15000   0 yellow 0.31 0.620201  1.000000  1.000000 
4 1200   1 yellow 0.32 0.567513  1.032258  0.915047 
5 1400   2 yellow 0.31 0.318197  1.000000  0.513055 
6 40000   0 green 0.29 0.947226  1.000000  1.000000 
7 3000   1 green 0.31 0.084243  1.068966  0.088937 
8 7000   2 green 0.32 0.961020  1.103448  1.014563 

passo dopo passo, in primo luogo troviamo gli indici denominatore:

012.351.641.061.
>>> ii = df.groupby("color")["experiment"].transform("idxmin") 
>>> ii 
0 0 
1 0 
2 0 
3 3 
4 3 
5 3 
6 6 
7 6 
8 6 
dtype: int64 

Quindi possiamo usare questo per indicizzare la struttura:

>>> df.loc[ii, cols] 
    value value2 
0 0.30 0.363953 
0 0.30 0.363953 
0 0.30 0.363953 
3 0.31 0.620201 
3 0.31 0.620201 
3 0.31 0.620201 
6 0.29 0.947226 
6 0.29 0.947226 
6 0.29 0.947226 

Poiché stiamo movimentazione l'allineamento stessi, dobbiamo chiamare .values per cadere giù alle sottostanti array-- altrimenti sarà pandi prova a superare in astuzia noi e allineare le cose correttamente in base agli indici.

Poi ci dividiamo:

>>> (df.loc[:,cols] /df.loc[ii, cols].values) 
     value value2 
0 1.000000 1.000000 
1 1.033333 0.601666 
2 0.966667 2.604924 
3 1.000000 1.000000 
4 1.032258 0.915047 
5 1.000000 0.513055 
6 1.000000 1.000000 
7 1.068966 0.088937 
8 1.103448 1.014563 

e infine unirsi a loro, rinominare le nuove colonne:

>>> df.join(new_cols.rename(columns=lambda x: "scaled_" + x)) 
     N experiment color value value2 scaled_value scaled_value2 
0 145000   0  red 0.30 0.363953  1.000000  1.000000 
1 14000   1  red 0.31 0.218978  1.033333  0.601666 
2 13000   2  red 0.29 0.948070  0.966667  2.604924 
3 15000   0 yellow 0.31 0.620201  1.000000  1.000000 
4 1200   1 yellow 0.32 0.567513  1.032258  0.915047 
5 1400   2 yellow 0.31 0.318197  1.000000  0.513055 
6 40000   0 green 0.29 0.947226  1.000000  1.000000 
7 3000   1 green 0.31 0.084243  1.068966  0.088937 
8 7000   2 green 0.32 0.961020  1.103448  1.014563 
Problemi correlati