2013-07-16 7 views
41

Mi chiedo se esiste un modo più semplice ed efficiente in termini di memoria per selezionare un sottoinsieme di righe e colonne da un DataFrame panda.Come convertire un sottoinsieme DataFrame pandas di colonne E righe in una matrice numpy?

Ad esempio, dato questo dataframe:

 
df = DataFrame(np.random.rand(4,5), columns = list('abcde')) 
print df 

      a   b   c   d   e 
0 0.945686 0.000710 0.909158 0.892892 0.326670 
1 0.919359 0.667057 0.462478 0.008204 0.473096 
2 0.976163 0.621712 0.208423 0.980471 0.048334 
3 0.459039 0.788318 0.309892 0.100539 0.753992 

voglio solo le righe in cui il valore di colonna 'c' è maggiore di 0,5, ma ho solo bisogno colonne 'b' e 'e' per quelle file.

Questo è il metodo che ho trovato - forse c'è un modo migliore di "panda"?

 
locs = [df.columns.get_loc(_) for _ in ['a', 'd']] 
print df[df.c > 0.5][locs] 

      a   d 
0 0.945686 0.892892 

Il mio obiettivo finale è quello di convertire il risultato in una matrice NumPy di ​​passare in un algoritmo sklearn di regressione, così ho utilizzerà il codice di cui sopra in questo modo:

 
training_set = array(df[df.c > 0.5][locs]) 

... e che Pix io da quando finisco con una copia di matrice enorme nella memoria. Forse c'è anche un modo migliore per farlo?

risposta

8

.loc accettare selettori di riga e colonna contemporaneamente (come fare .ix/.iloc FYI) Anche in un solo passaggio.

In [1]: df = DataFrame(np.random.rand(4,5), columns = list('abcde')) 

In [2]: df 
Out[2]: 
      a   b   c   d   e 
0 0.669701 0.780497 0.955690 0.451573 0.232194 
1 0.952762 0.585579 0.890801 0.643251 0.556220 
2 0.900713 0.790938 0.952628 0.505775 0.582365 
3 0.994205 0.330560 0.286694 0.125061 0.575153 

In [5]: df.loc[df['c']>0.5,['a','d']] 
Out[5]: 
      a   d 
0 0.669701 0.451573 
1 0.952762 0.643251 
2 0.900713 0.505775 

E se si desidera che i valori (anche se questo dovrebbe passare direttamente a sklearn come è); i frame supportano l'interfaccia dell'array

In [6]: df.loc[df['c']>0.5,['a','d']].values 
Out[6]: 
array([[ 0.66970138, 0.45157274], 
     [ 0.95276167, 0.64325143], 
     [ 0.90071271, 0.50577509]]) 
+0

Più elegante. Qual è la differenza tra .ix e .loc? –

+0

loc non tenterà di utilizzare un numero (ad esempio 1) come argomento posizionale (e alza invece); vedere i principali documenti panda/selezionare i dati – Jeff

70

Utilizzare il suo valore direttamente:

In [79]: df[df.c > 0.5][['b', 'e']].values 
Out[79]: 
array([[ 0.98836259, 0.82403141], 
     [ 0.337358 , 0.02054435], 
     [ 0.29271728, 0.37813099], 
     [ 0.70033513, 0.69919695]]) 
+0

Non sapevo dell'attributo .values. Molto bella! Inoltre, leggermente più pulito da quando hai eliminato le virgolette singole e le parentesi e invece hai usato direttamente df.c. –

+1

bello, ma come è diverso da 'as_matrix' però? – dashesy

+5

Solo un aggiornamento, poiché mi chiedevo solo la differenza tra as_matrix e .values ​​(dato che uso solo .values). Si scopre che as_matrix è fornito solo per la compatibilità con le versioni precedenti e che si consiglia di utilizzare .values. Vedi http://pandas.pydata.org/pandas-docs/version/0.17.1/generated/pandas.DataFrame.as_matrix.html – DkM

16

Forse qualcosa di simile per il primo problema, si può semplicemente accedere alle colonne con i loro nomi:

>>> df = pd.DataFrame(np.random.rand(4,5), columns = list('abcde')) 
>>> df[df['c']>.5][['b','e']] 
      b   e 
1 0.071146 0.132145 
2 0.495152 0.420219 

Per il secondo problema:

>>> df[df['c']>.5][['b','e']].values 
array([[ 0.07114556, 0.13214495], 
     [ 0.49515157, 0.42021946]])