2012-05-29 2 views
7

Voglio dire qualcosa del genere:Come discretizzare i valori in un DataFrame di panda e convertirli in una matrice binaria?

Ho un DataFrame con colonne che possono essere categoriali o nominali. Per ogni osservazione (riga), voglio generare una nuova riga in cui ogni possibile valore per le variabili è ora la sua stessa variabile binaria. Ad esempio, questa matrice (prima riga sia etichette di colonna)

'a'  'b'  'c' 
one  0.2  0 
two  0.4  1 
two  0.9  0 
three 0.1  2 
one  0.0  4 
two  0.2  5 

verrebbe convertito in qualcosa di simile:

'a'    'b'             'c' 
one two three [0.0,0.2) [0.2,0.4) [0.4,0.6) [0.6,0.8) [0.8,1.0] 0 1 2 3 4 5 

1 0  0  0   1   0   0   0  1 0 0 0 0 0 
0 1  0  0   0   0   0   1  0 1 0 0 0 0 
0 1  0  0   0   0   0   1  1 0 0 0 0 0 
0 0  1  1   0   0   0   0  0 0 1 0 0 0 
1 0  0  1   0   0   0   0  0 0 0 0 1 0 
0 1  0  0   1   0   0   0  0 0 0 0 0 1 

Ogni (colonna) variabile nella matrice iniziale ottenere raggruppate in tutte le possibili valori . Se è categoriale, ogni valore possibile diventa una nuova colonna. Se si tratta di un float, i valori vengono divisi in un modo (ad esempio, dividendo sempre in 10 contenitori). Se è un int, allora può essere ogni possibile valore int, o forse anche binning.

FYI: nella mia vera applicazione, la tabella ha fino a 2 milioni di righe e la matrice "espansa" completa può avere centinaia di colonne.

Esiste un modo semplice per eseguire questa operazione?

Separatamente, vorrei anche saltare questo passaggio, poiché sto davvero cercando di calcolare una tabella Burt (che è una matrice simmetrica delle tabelle incrociate). C'è un modo semplice per fare qualcosa di simile con la funzione crosstab? Altrimenti, calcolare la tabulazione incrociata è solo una semplice moltiplicazione di matrice.

risposta

4

È possibile utilizzare un qualche tipo di trasmissione:

In [58]: df 
    Out[58]: 
      a b c 
    0 one 0.2 0 
    1 two 0.4 1 
    2 two 0.9 0 
    3 three 0.1 2 
    4 one 0.0 4 
    5 two 0.2 5 

    In [41]: (df.a.values[:,numpy.newaxis] == df.a.unique()).astype(int) 
    Out[41]: 
    array([[1, 0, 0], 
      [0, 1, 0], 
      [0, 1, 0], 
      [0, 0, 1], 
      [1, 0, 0], 
      [0, 1, 0]]) 

    In [54]: ((0 <= df.b.values[:,numpy.newaxis]) & (df.b.values[:,numpy.newaxis] < 0.2)).astype(int) 
    Out[54]: 
    array([[0], 
      [0], 
      [0], 
      [1], 
      [1], 
      [0]]) 

    In [59]: (df.c.values[:,numpy.newaxis] == df.c.unique()).astype(int) 
    Out[59]: 
    array([[1, 0, 0, 0, 0], 
      [0, 1, 0, 0, 0], 
      [1, 0, 0, 0, 0], 
      [0, 0, 1, 0, 0], 
      [0, 0, 0, 1, 0], 
      [0, 0, 0, 0, 1]]) 

E poi unire tutti i pezzi insieme con pandas.concat o simili.

+0

C'è un modo per eseguire qualcosa di simile da un sapiente uso di 'crosstab' o' 'pivot_table' o stack' o qualcosa di simile? –

+0

Certo, per 'a' e 'c' è facile: 'pandas.concat ([pandas.crosstab (df.index, [df.a]), pandas.crosstab (df.index, [df.c])] , asse = 1) '.Per 'b', suppongo che si possa fare specificando un corretto 'aggfunc' in 'crosstab' ... – lbolla

1

Mettere insieme un paio di altri commenti in un unico risposta di risposta PO domande.

d = {'a' : pd.Series(['one', 'two', 'two', 'three', 'one', 'two']), 
    'b' : pd.Series([0.2, 0.4, 0.9, 0.1, 0.0, 0.2]), 
    'c' : pd.Series([0, 1, 0, 2, 4, 5]) } 

data = pd.DataFrame(d) 
a_cols = pd.crosstab(data.index, [data.a]) 
b_bins = pd.cut(data.b, [0.0, 0.2, 0.4, 0.6, 0.8, 1.0], right=False) 
b_cols = pd.crosstab(data.index, b_bins) 
c_cols = pd.crosstab(data.index, [data.c],) 
new_data = a_cols.join(b_cols).join(c_cols) 
new_data.index.names = [''] 
print new_data.to_string() 

""" 
     one three two [0, 0.2) [0.2, 0.4) [0.4, 0.6) [0.8, 1) 0 1 2 4 5 

    0 1  0 0   0   1   0   0 1 0 0 0 0 
    1 0  0 1   0   0   1   0 0 1 0 0 0 
    2 0  0 1   0   0   0   1 1 0 0 0 0 
    3 0  1 0   1   0   0   0 0 0 1 0 0 
    4 1  0 0   1   0   0   0 0 0 0 1 0 
    5 0  0 1   0   1   0   0 0 0 0 0 1 
""" 
3

Dubito che tu possa battere la semplicità di patsy. E 'stato progettato proprio per questo compito:

>>> from patsy import dmatrix 
>>> dmatrix('C(a) + C(b) + C(c) - 1', df, return_type='dataframe') 

    C(a)[one] C(a)[three] C(a)[two] C(b)[T.0.1] C(b)[T.0.2] C(b)[T.0.4] C(b)[T.0.9] C(c)[T.1] C(c)[T.2] C(c)[T.4] C(c)[T.5] 
0   1   0   0   0   1   0    0   0   0   0   0 
1   0   0   1   0   0   1    0   1   0   0   0 
2   0   0   1   0   0   0    1   0   0   0   0 
3   0   1   0   1   0   0    0   0   1   0   0 
4   1   0   0   0   0   0    0   0   0   1   0 
5   0   0   1   0   1   0    0   0   0   0   1 

Qui i mezzi C(a) convertire la variabile categorica e il -1 è quello di evitare l'emissione di una colonna di intercettazione.

5

Per colonne etichettate come la colonna a e c nell'esempio, è possibile utilizzare il metodo build-in panda get_dummies().

Es .:

import pandas as pd 
s1 = ['a', 'b', np.nan] 
pd.get_dummies(s1) 
     a b 
    0 1 0 
    1 0 1 
    2 0 0 
+0

Whoa! Questo è un grande –