2015-07-27 10 views
15

Sto lavorando girando una lista di record con due colonne (A e B) in una rappresentazione a matrice. Ho usato la funzione pivot all'interno dei panda, ma il risultato è abbastanza grande. I panda supportano la rotazione in un formato spartano? So che posso girarlo e trasformarlo in una sorta di rappresentazione sparsa, ma non è elegante come vorrei. Il mio obiettivo finale è usarlo come input per un modello predittivo.Creazione efficiente di tabelle pivot sparse nei panda?

In alternativa, c'è qualche tipo di capacità di pivot sparsa al di fuori dei panda?

edit: qui è un esempio di un perno non sparse

import pandas as pd 
frame=pd.DataFrame() 
frame['person']=['me','you','him','you','him','me'] 
frame['thing']=['a','a','b','c','d','d'] 
frame['count']=[1,1,1,1,1,1] 

frame 

    person thing count 
0  me  a  1 
1 you  a  1 
2 him  b  1 
3 you  c  1 
4 him  d  1 
5  me  d  1 

frame.pivot('person','thing') 

     count    
thing  a b c d 
person     
him  NaN 1 NaN 1 
me   1 NaN NaN 1 
you   1 NaN 1 NaN 

Questo crea una matrice che potrebbero contenere tutte le possibili combinazioni di persone e cose, ma non è scarsa.

http://docs.scipy.org/doc/scipy/reference/sparse.html

matrici sparse occupano meno spazio perché possono implicare cose come NaN o 0. Se ho un grande insieme di dati, questa funzione di rotazione può generare una matrice che dovrebbe essere sparsa a causa del gran numero di di NaN o 0s. Speravo di poter risparmiare un sacco di spazio/memoria generando qualcosa che era raro da un blocco piuttosto che creare una matrice densa e quindi convertirlo in uno scarso.

+1

Potresti fornire qualche esempio di input, output, codice? – Skorpeo

+0

cosa significa sparse? – AZhao

+0

@AZhao È un termine matematico https://en.m.wikipedia.org/wiki/Sparse_matrix –

risposta

26

Ecco un metodo che crea una matrice scipy sparsa basata su dati e indici di persone e cose. person_u e thing_u sono elenchi che rappresentano le voci univoche per le righe e le colonne di pivot che si desidera creare. Nota: si presume che la colonna dei conteggi abbia già il valore desiderato.

from scipy.sparse import csr_matrix 

person_u = list(sort(frame.person.unique())) 
thing_u = list(sort(frame.thing.unique())) 

data = frame['count'].tolist() 
row = frame.person.astype('category', categories=person_u).cat.codes 
col = frame.thing.astype('category', categories=thing_u).cat.codes 
sparse_matrix = csr_matrix((data, (row, col)), shape=(len(person_u), len(thing_u))) 

>>> sparse_matrix 
<3x4 sparse matrix of type '<type 'numpy.int64'>' 
    with 6 stored elements in Compressed Sparse Row format> 

>>> sparse_matrix.todense() 

matrix([[0, 1, 0, 1], 
     [1, 0, 0, 1], 
     [1, 0, 1, 0]]) 

Sulla base della sua domanda iniziale, la matrice sparsa SciPy dovrebbe essere sufficiente per le vostre esigenze, ma se desiderate avere un dataframe rada è possibile effettuare le seguenti operazioni:

dfs=pd.SparseDataFrame([ pd.SparseSeries(sparse_matrix[i].toarray().ravel(), fill_value=0) 
           for i in np.arange(sparse_matrix.shape[0]) ], index=person_u, columns=thing_u, default_fill_value=0) 

>>> dfs 
    a b c d 
him 0 1 0 1 
me 1 0 0 1 
you 1 0 1 0 

>>> type(dfs) 
pandas.sparse.frame.SparseDataFrame 
+1

Grazie! Speravo davvero di evitare la creazione di una matrice densa e quindi di usare to_sparse() perché così facendo si richiede ancora la quantità di memoria necessaria per la matrice densa in un punto o in un altro. Mi sento come se ci fossero altre funzioni di Pandas che possono generare dati sparsi, ma forse ho torto o forse devo guardare altrove. – neelshiv

+0

Molto interessante. Il mio piano era di provare qualcosa di simile se non ci fosse una soluzione là fuori, ma avrei avuto bisogno di imparare un po 'di più sulle matrici scipy sparse prima. Ora posso imparare dal tuo codice. Grazie! – neelshiv

+0

perché si ordina l'elenco, ad es. person_u = list (sort (frame.person.unique())) .. sembra che la matrice finale (sparse_matrix) non corrisponda al dataframe – kitchenprinzessin

2

ho avuto un simile problema e mi sono imbattuto in questo post. L'unica differenza era che avevo due colonne nello DataFrame che definiscono la "dimensione della riga" (i) della matrice di output. Ho pensato che potesse essere un'interessante generalizzazione, ho usato il grouper:

# function 
import pandas as pd 

from scipy.sparse import csr_matrix 

def df_to_sm(data, vars_i, vars_j): 
    grpr_i = data.groupby(vars_i).grouper 

    idx_i = grpr_i.group_info[0] 

    grpr_j = data.groupby(vars_j).grouper 

    idx_j = grpr_j.group_info[0] 

    data_sm = csr_matrix((data['val'].values, (idx_i, idx_j)), 
         shape=(grpr_i.ngroups, grpr_j.ngroups)) 

    return data_sm, grpr_i, grpr_j 


# example 
data = pd.DataFrame({'var_i_1' : ['a1', 'a1', 'a1', 'a2', 'a2', 'a3'], 
        'var_i_2' : ['b2', 'b1', 'b1', 'b1', 'b1', 'b4'], 
        'var_j_1' : ['c2', 'c3', 'c2', 'c1', 'c2', 'c3'], 
        'val' : [1, 2, 3, 4, 5, 6]}) 

data_sm, _, _ = df_to_sm(data, ['var_i_1', 'var_i_2'], ['var_j_1']) 

data_sm.todense() 
+0

Bello! Al momento non sto usando pivot sparsi, ma cercherò di verificarlo. Grazie per aver contribuito! – neelshiv

Problemi correlati