2016-03-01 23 views
11

Voglio applicare il ridimensionamento (usando StandardScaler() da sklearn.preprocessing) ad un dataframe panda. Il seguente codice restituisce una matrice numpy, quindi perdo tutti i nomi delle colonne e gli indeces. Questo non è quello che voglio.Come utilizzare sklearn fit_transform con i panda e restituire dataframe invece di matrice numpy?

features = df[["col1", "col2", "col3", "col4"]] 
autoscaler = StandardScaler() 
features = autoscaler.fit_transform(features) 

"soluzione" Un ho trovato on-line è:

features = features.apply(lambda x: autoscaler.fit_transform(x)) 

E sembra funzionare, ma conduce ad un DeprecationWarning:

/usr/lib/python3.5/site -packages/sklearn/preelaborazione/data.py: 583: DeprecationWarning: Passaggio array 1d come dati è obsoleto in 0,17 e solleverà ValueError a 0.19. Rimodellare i dati sia utilizzando X.reshape (-1, 1) se i dati ha una sola caratteristica o X.reshape (1, -1) se contiene un singolo campione.

pertanto provato:

features = features.apply(lambda x: autoscaler.fit_transform(x.reshape(-1, 1))) 

Ma questo dà:

Traceback (chiamata più recente scorso): File "./analyse.py", la linea 91, in caratteristiche = features.apply (lambda x: autoscaler.fit_transform (x.reshape (-1, 1))) file "/usr/lib/python3.5/site-packages/pandas/core/frame.py", linea 3972, in si applica return self._apply_standard (f, axis, reduce = reduce) File "/usr/lib/python3.5/site-packages/pandas/core/frame.py", riga 4081, in _apply_standard result = self._constructor (dati = risultati, indice = indice) File "/usr/lib/python3.5/site-packages/pandas/core/frame.py", riga 226, in init mgr = self._init_dict (dati, index, columns, dtype = dtype) File "/usr/lib/python3.5/site-packages/pandas/core/frame.py", riga 363, in _init_dict dtype = dtype) File "/ usr/lib/python3.5/site-packages/pandas/core/frame.py ", riga 5163, in _arrays_to_mgr array = _homogenize (array, indice, dtype) File" /usr/lib/python3.5/site-packages/pandas /core/frame.py ", riga 5477, in _homogenize raise_cast_failure = False) File "/usr/lib/python3.5/site-packages/pandas/core/series.py", riga 2885, in _sanitize_array raise Exception ('I dati devono essere 1-dimensionali') Eccezione: i dati devono essere 1-dimensionali

Come si applica il ridimensionamento al dataframe panda, lasciando intatto il dataframe? Senza copiare i dati, se possibile.

risposta

19

si potrebbe convertire il dataframe come un array NumPy utilizzando as_matrix(). Esempio su un set di dati casuali:

Edit: Cambiare as_matrix()-values, (non cambia il risultato) per l'ultima frase dei as_matrix() documenti di cui sopra:

In generale, è consigliabile usare '.values'.

import pandas as pd 
import numpy as np #for the random integer example 
df = pd.DataFrame(np.random.randint(0.0,100.0,size=(10,4)), 
       index=range(10,20), 
       columns=['col1','col2','col3','col4'], 
       dtype='float64') 

nota, gli indici sono 10-19:

In [14]: df.head(3) 
Out[14]: 
    col1 col2 col3 col4 
    10 3 38 86 65 
    11 98 3 66 68 
    12 88 46 35 68 

Ora fit_transform il dataframe per ottenere il scaled_featuresarray:

from sklearn.preprocessing import StandardScaler 
scaled_features = StandardScaler().fit_transform(df.values) 

In [15]: scaled_features[:3,:] #lost the indices 
Out[15]: 
array([[-1.89007341, 0.05636005, 1.74514417, 0.46669562], 
     [ 1.26558518, -1.35264122, 0.82178747, 0.59282958], 
     [ 0.93341059, 0.37841748, -0.60941542, 0.59282958]]) 

Assegnare i dati in scala per un dataframe (Nota : utilizzare gli argomenti delle parole chiave index e columns per mantenere indici iginal e nomi di colonna:

scaled_features_df = pd.DataFrame(scaled_features, index=df.index, columns=df.columns) 

In [17]: scaled_features_df.head(3) 
Out[17]: 
    col1 col2 col3 col4 
10 -1.890073 0.056360 1.745144 0.466696 
11 1.265585 -1.352641 0.821787 0.592830 
12 0.933411 0.378417 -0.609415 0.592830 

Modifica 2:

sono imbattuto nel pacchetto sklearn-pandas. È incentrato sul rendere lo scikit-learn più facile da usare con i panda. sklearn-pandas è particolarmente utile quando è necessario applicare più di un tipo di trasformazione ai sottoinsiemi di colonna dello DataFrame, uno scenario più comune. È documentato, ma è così che otterresti la trasformazione che abbiamo appena eseguito.

from sklearn_pandas import DataFrameMapper 

mapper = DataFrameMapper([(df.columns, StandardScaler())]) 
scaled_features = mapper.fit_transform(df.copy(), 4) 
scaled_features_df = pd.DataFrame(scaled_features, index=df.index, columns=df.columns) 
+1

Grazie per la risposta, ma il problema è che le righe vengono rinumerate quando il nuovo dataframe viene creato dall'array. Il dataframe originale non contiene righe numerate consecutivamente perché alcune di esse sono state rimosse. Suppongo di poter aggiungere anche una parola chiave index = [...] con i vecchi valori di indice. Se aggiorni la tua risposta di conseguenza, posso accettarla. – louic

+0

Spero che la modifica aiuti, penso che la tua intuizione sull'impostazione dei valori dell'indice dal primo df sia corretta. I numeri che ho usato sono consecutivi ... (volevo solo mostrare che puoi resettarli a qualsiasi cosa e la gamma (10,20) era la migliore che potessi pensare, ma funzionerà con qualsiasi indice casuale sul df originale .HHH! – Kevin

+0

Grazie mille Kevin! – louic

Problemi correlati