2014-10-16 83 views
33

Ho un dataframe in panda in cui ogni colonna ha un intervallo di valori diverso. Ad esempio:Normalizza colonne del frame di dati panda

df:

A  B C 
1000 10 0.5 
765 5 0.35 
800 7 0.09 

Qualsiasi idea di come posso normalizzare le colonne di questa dataframe dove ogni valore è compreso tra 0 e 1?

mio output desiderato è:

A  B C 
1  1 1 
0.765 0.5 0.7 
0.8 0.7 0.18(which is 0.09/0.5) 
+0

c'è una funzione di applicare, per esempio frame.apply (f, axis = 1) dove f è una funzione che fa qualcosa con una riga ... – tschm

risposta

44

È possibile utilizzare il pacchetto di sklearn e delle sue utility di pre-elaborazione associati per normalizzare i dati.

from sklearn import preprocessing 

x = df.values #returns a numpy array 
min_max_scaler = preprocessing.MinMaxScaler() 
x_scaled = min_max_scaler.fit_transform(x) 
df = pandas.DataFrame(x_scaled) 

Per ulteriori informazioni consultare le scikit-learn documentation su dati di pre-elaborazione: caratteristiche di ridimensionamento da un intervallo.

+6

penso che questo eliminerà i nomi delle colonne, che potrebbe essere uno dei motivi per cui op sta usando i dataframe nella prima posto. – pietz

+4

Ciò normalizzerà le righe e non le colonne, a meno che non la si trasponga prima. Per fare ciò che chiede Q: 'pd.DataFrame (min_max_scaler.fit_transform (df.T), columns = df.columns, index = df.index)' – hobs

+2

@pietz per mantenere i nomi delle colonne, vedi [questo post] (https : //stackoverflow.com/a/29907472/588437). Sostituire fondamentalmente l'ultima riga con , 'df = pandas.DataFrame (x_scaled, columns = df.columns)' – ijoseph

9

Il tuo problema è in realtà un semplice trasformare agendo sulle colonne:

def f(s): 
    return s/s.max() 

frame.apply(f, axis=0) 

o anche più concisa:

frame.apply(lambda x: x/x.max(), axis=0) 
4

penso che il modo migliore per farlo che in panda è solo

df = df/df.max().astype(np.float64) 

Modifica Se nel data frame negativ e numeri sono presenti si dovrebbe usare invece

df = df/df.loc[df.abs().idxmax()].astype(np.float64) 
+0

Nel caso in cui tutti i valori di una colonna siano zero, questo non funzionerà – ahajib

+0

dividendo il valore corrente per il massimo non sarà darti una normalizzazione corretta a meno che il minimo sia 0. – pietz

+0

Sono d'accordo, ma questo è quello che l'OT chiedeva (vedi il suo esempio) – Daniele

21

Sulla base di questo post: https://stats.stackexchange.com/questions/70801/how-to-normalize-data-to-0-1-range

È possibile effettuare le seguenti operazioni:

def normalize(df): 
    result = df.copy() 
    for feature_name in df.columns: 
     max_value = df[feature_name].max() 
     min_value = df[feature_name].min() 
     result[feature_name] = (df[feature_name] - min_value)/(max_value - min_value) 
    return result 

Non c'è bisogno di rimanere preoccuparsi se i vostri valori sono negativi o positivi. E i valori devono essere ben distribuite tra 0 e 1.

43

un modo semplice utilizzando Pandas: (qui voglio usare significare la normalizzazione)

normalized_df=(df-df.mean())/df.std() 

usare min-max normalizzazione:

normalized_df=(df-df.min())/(df.max()-df.min()) 
+3

mi piace questo. è breve, è espressivo e conserva le informazioni dell'intestazione. ma penso che sia necessario sottrarre anche il minimo al denominatore. – pietz

+1

grazie per il tuo commento. Modifico il denominatore. – Cina

9

Se vi piace utilizzando il pacchetto sklearn, è possibile mantenere i nomi di colonna e indice utilizzando panda loc in questo modo:

from sklearn.preprocessing import MinMaxScaler 

scaler = MinMaxScaler() 
scaled_values = scaler.fit_transform(df) 
df.loc[:,:] = scaled_values 
1

La soluzione offerta da Sandman e Praveen è molto buona. L'unico problema è che se hai variabili categoriali in altre colonne del tuo frame di dati, questo metodo avrà bisogno di alcuni aggiustamenti.

La mia soluzione a questo tipo di problema è la seguente:

from sklearn import preprocesing 
x = pd.concat([df.Numerical1, df.Numerical2,df.Numerical3]) 
min_max_scaler = preprocessing.MinMaxScaler() 
x_scaled = min_max_scaler.fit_transform(x) 
x_new = pd.DataFrame(x_scaled) 
df = pd.concat([df.Categoricals,x_new]) 
0

Semplice è bello:

df["A"] = df["A"]/df["A"].max() 
df["B"] = df["B"]/df["B"].max() 
df["C"] = df["C"]/df["C"].max()