2016-01-10 9 views
5

Dato uno Sframe in quanto tale:Converti graphlab sframe in un dizionario di {chiave: valori}

+------+-----------+-----------+-----------+-----------+-----------+-----------+ 
| X1 |  X2 |  X3 |  X4 |  X5 |  X6 |  X7 | 
+------+-----------+-----------+-----------+-----------+-----------+-----------+ 
| the | -0.060292 | 0.06763 | -0.036891 | 0.066684 | 0.024045 | 0.099091 | 
| , | 0.026625 | 0.073101 | -0.027073 | -0.019504 | 0.04173 | 0.038811 | 
| . | -0.005893 | 0.093791 | 0.015333 | 0.046226 | 0.032791 | 0.110069 | 
| of | -0.050371 | 0.031452 | 0.04091 | 0.033255 | -0.009195 | 0.061086 | 
| and | 0.005456 | 0.063237 | -0.075793 | -0.000819 | 0.003407 | 0.053554 | 
| to | 0.01347 | 0.043712 | -0.087122 | 0.015258 | 0.08834 | 0.139644 | 
| in | -0.019466 | 0.077509 | -0.102543 | 0.034337 | 0.130886 | 0.032195 | 
| a | -0.072288 | -0.017494 | -0.018383 | 0.001857 | -0.04645 | 0.133424 | 
| is | 0.052726 | 0.041903 | 0.163781 | 0.006887 | -0.07533 | 0.108394 | 
| for | -0.004082 | -0.024244 | 0.042166 | 0.007032 | -0.081243 | 0.026162 | 
| on | -0.023709 | -0.038306 | -0.16072 | -0.171599 | 0.150983 | 0.042044 | 
| that | 0.062037 | 0.100348 | -0.059753 | -0.041444 | 0.041156 | 0.166704 | 
| ) | 0.052312 | 0.072473 | -0.02067 | -0.015581 | 0.063368 | -0.017216 | 
| ( | 0.051408 | 0.186162 | 0.03028 | -0.048425 | 0.051376 | 0.004989 | 
| with | 0.091825 | -0.081649 | -0.087926 | -0.061273 | 0.043528 | 0.107864 | 
| was | 0.046042 | -0.058529 | 0.040581 | 0.067748 | 0.053724 | 0.041067 | 
| as | 0.025248 | -0.012519 | -0.054685 | -0.040581 | 0.051061 | 0.114956 | 
| it | 0.028606 | 0.106391 | 0.025065 | 0.023486 | 0.011184 | 0.016715 | 
| by | -0.096704 | 0.150165 | -0.01775 | -0.07178 | 0.004458 | 0.098807 | 
| be | -0.109489 | -0.025908 | 0.025608 | 0.076263 | -0.047246 | 0.100489 | 
+------+-----------+-----------+-----------+-----------+-----------+-----------+ 

Come posso convertire lo Sframe in un dizionario in modo tale che X1 colonna è la chiave e X2 a X7 come il np.array()?

Ho provato scorrendo la Sframe originale riga per riga e fare qualcosa del genere:

>>> import graphlab as gl 
>>> import numpy as np 
>>> x = gl.SFrame() 
>>> a = np.array([1,2,3]) 
>>> w = 'foo' 
>>> x.append(gl.SFrame({'word':[w], 'vector':[a]})) 
Columns: 
    vector array 
    word str 

Rows: 1 

Data: 
+-----------------+------+ 
|  vector  | word | 
+-----------------+------+ 
| [1.0, 2.0, 3.0] | foo | 
+-----------------+------+ 
[1 rows x 2 columns] 

C'è un altro modo di fare lo stesso?


CURA

Dopo aver provato @papayawarrior soluzione, funziona se riesco a caricare l'intera dataframe nella memoria, ma ci sono alcune quriks che lo rende strano.

Supponendo che il mio ingresso originale al Sframe è come presentato sopra (con 501 colonne) ma in .csv di file, ho il codice per leggerle nel dizionario desiderato:

def get_embeddings(embedding_gzip, size): 
    coltypes = [str] + [float] * size 
    sf = gl.SFrame.read_csv('compose-vectors/' + embedding_gzip, delimiter='\t', column_type_hints=coltypes, header=False, quote_char='\0') 
    sf = sf.pack_columns(['X'+str(i) for i in range(2, size+1)]) 
    df = sf.to_dataframe().set_index('X1') 
    print list(df) 
    return df.to_dict(orient='dict')['X2'] 

Ma stranamente si dà questo errore:

File "sts_compose.py", line 28, in get_embeddings 
    return df.to_dict(orient='dict')['X2'] 
KeyError: 'X2' 

Così quando controllo per i nomi di colonna prima della conversione al dizionario, ho scoperto che i miei nomi delle colonne non sono 'X1' e 'X2' ma list(df) stampe ['X501', 'X3'].

C'è qualcosa di sbagliato nel modo in cui ho convertito lo graphlab.SFrame -> pandas.DataFrame -> dict?

so di poter risolvere il problema in questo modo, invece, ma la domanda rimane: "Come ha fatto i nomi delle colonne diventano così strano?":

def get_embeddings(embedding_gzip, size): 
    coltypes = [str] + [float] * size 
    sf = gl.SFrame.read_csv('compose-vectors/' + embedding_gzip, delimiter='\t', column_type_hints=coltypes, header=False, quote_char='\0') 
    sf = sf.pack_columns(['X'+str(i) for i in range(2, size+1)]) 
    df = sf.to_dataframe().set_index('X1') 
    col_names = list(df) 
    return df.to_dict(orient='dict')[col_names[1]] 
+0

quanto riguarda la questione della modifica, la risposta di Adrien Renaud fa uso del parametro 'new_column_name' nella funzione' SFrame.pack_columns', che credo sia una buona idea, in questo caso per assicurarsi di sapere i vostri dati colonna. – papayawarrior

+1

Un altro piccolo consiglio è quello di rinominare la colonna di parole, quindi utilizzare il parametro 'column_prefix' in' pack_columns' per evitare la comprensione delle liste. Ho appena aggiornato la mia risposta per mostrarlo. – papayawarrior

risposta

2

modificato per corrispondere a nuove domande nel post.

@Adrien Renaud è a posto con il metodo SFrame.pack_columns, ma io suggerirei di usare il dataframe Panda to_dict per l'ultima domanda se il set di dati si inserisce in memoria.

>>> import graphlab as gl 
>>> sf = gl.SFrame({'X1': ['cat', 'dog'], 'X2': [1, 2], 'X3': [3, 4]}) 
>>> sf 
+-----+----+----+ 
| X1 | X2 | X3 | 
+-----+----+----+ 
| cat | 1 | 3 | 
| dog | 2 | 4 | 
+-----+----+----+ 

>>> sf2 = sf.rename({'X1': 'word'}) 
>>> sf2 = sf.pack_columns(column_prefix='X', new_column_name='vector') 
>>> sf2 
+------+--------+ 
| word | vector | 
+------+--------+ 
| cat | [1, 3] | 
| dog | [2, 4] | 
+------+--------+ 

>>> df = sf2.to_dataframe().set_index('word') 
>>> result = df.to_dict(orient='dict')['vector'] 
>>> result 
{'cat': [1, 3], 'dog': [2, 4]} 
+0

Grazie! Questo aiuta molto. Domanda veloce, 'type (array [0] [results])' restituisce una lista, li ho espressamente lanciati in un 'np.array()' per la manipolazione del vettore, giusto? – alvas

+0

Non sono completamente sicuro di cosa intenda con 'array [0]', ma supponendo che tu intenda 'result ['cat']', allora sì, sarà un elenco e dovrai eseguirlo esplicitamente in un file matrice numpy. – papayawarrior

+0

Sì! Grazie ancora! Lanciarli in una serie numerica realizza il dizionario desiderato di cui ho bisogno per i miei scopi. Purtroppo, avere risultati in un dizionario python significa che devo avere abbastanza RAM per memorizzare l'intero dizionario. È possibile eseguire il cast in SFrame o DataFrame in modo tale che graphlab o panda utilizzino tcmalloc per gestire il dizionario di grandi dimensioni? – alvas

3

C'è un altro modo di fare lo stesso? Sì, è possibile utilizzare il metodo pack_columns dalla classe SFrame.

import graphlab as gl 
data = gl.SFrame() 
data.add_column(gl.SArray(['foo', 'bar']), 'X1') 
data.add_column(gl.SArray([1., 3.]), 'X2') 
data.add_column(gl.SArray([2., 4.]), 'X3') 
print data 
+-----+-----+-----+ 
| X1 | X2 | X3 | 
+-----+-----+-----+ 
| foo | 1.0 | 2.0 | 
| bar | 3.0 | 4.0 | 
+-----+-----+-----+ 
[2 rows x 3 columns] 

import array 
data = data.pack_columns(['X2', 'X3'], dtype=array.array, new_column_name='vector') 
data = data.rename({'X1':'word'}) 
print data 
+------+------------+ 
| word | vector | 
+------+------------+ 
| foo | [1.0, 2.0] | 
| bar | [3.0, 4.0] | 
+------+------------+ 
[2 rows x 2 columns] 

b=data['vector'][0] 
print type(b) 
<type 'array.array'> 

Come posso convertire lo Sframe in un dizionario come quella colonna X1 è la chiave e X2 a X7 come np.array()?

Non ho trovato alcun metodo incorporato per convertire uno SFrame in un dettato. Si potrebbe provare quanto segue (che potrebbe essere molto lento):

a={} 
def dump_sframe_to_dict(row, a): 
    a[row['word']]=row['vector'] 
data.apply(lambda x: dump_sframe_to_dict(x, a)) 
print a 
{'foo': array('d', [1.0, 2.0]), 'bar': array('d', [3.0, 4.0])} 
+0

Breve domanda, quando si legge una riga, diciamo 'data [0]', quindi si prenda la colonna vettoriale, 'data [0] [vector]' e quindi si faccia un 'type (data [0] [vector]) 'hai ricevuto una lista o una matrice numpy? – alvas

+1

Facendo 'data ['vector'] [0]', ottengo un'istanza di 'array.array'. –

Problemi correlati