2017-10-06 6 views
0

On suppose une liste de listes avec des chaînes comme ci-dessousGénération d'une matrice creuse donné une liste des listes avec des chaînes

docs = [["hello", "world", "hello"], ["goodbye", "cruel"]] 

Comment fait-on pour créer une matrice creuse où chaque ligne représente une sous-liste de la liste ci-dessus et chaque colonne représente une chaîne de jetons comme "cruel" dans la sous-liste.

J'ai regardé les docs scipy here et quelques autres messages de stackoverflow, mais, celui-ci n'est pas clair pour moi.

row_idx = 0                                 
col_idx = 0                                 
rows = []                                  
cols = []                                  
vals = []                                  
for doc in tokens_list:                              
    col_idx = 0                                
    for token in doc:                               
     rows.append(row_idx)                             
     cols.append(col_idx)                             
     col_idx = col_idx + 1                             
     vals.append(1)                               
    row_idx = row_idx + 1                                                                                         
X = csr_matrix((vals, (rows, cols)))   

J'ai essayé quelque chose comme ci-dessus, mais j'ai le sentiment que ce n'est pas juste et je ne peux pas se rapporter aux exemples dans la documentation scipy.

+0

Quelle est la sortie attendue? – Divakar

+0

Avez-vous à le faire avec des listes? C'est extrêmement agréable, simple et direct avec les dictionnaires! – agaidis

+0

@Divakar L'entrée réelle est [['isn', 't', 'ceci', 'film', 'génial'], ['horrible', 'horrible', 'film']] avec la sortie attendue je crois étant [[1, 0, 1, 1, 1, 1], [0, 2, 0, 1, 0, 0]]. – Sanchayan

Répondre

0

Je créerais un dictionnaire au lieu d'utiliser des listes. Ensuite, vous pouvez avoir un tuple (ligne, col) comme clé et la valeur sera tout ce qui est contenu sur cette ligne, col index. Vous obtenez la densité en ajoutant seulement les éléments au dictionnaire qui ne sont pas null, 0, etc. dans votre matrice.

Vous pouvez également remplacer les tuples par des listes.

0

L'exemple sur les documents csr génère les attributs directement csr, indptr, indices et data. Les entrées pour coo sont row, col et data. La différence est dans les row et indptr; les autres attributs sont les mêmes.

À première vue, il vous manque le dictionnaire vocabulary. Il est facile de faire correspondre row avec l'index de l'élément dans la liste. Mais col doit cartographier, en quelque sorte, sur une liste ou un dictionnaire de mots.

In [498]: docs = [["hello", "world", "hello"], ["goodbye", "cruel", "world"]] 
In [499]: indptr = [0] 
In [500]: indices = [] 
In [501]: data = [] 
In [502]: vocabulary = {} # a dictionary 
In [503]: for d in docs: 
    ...: ...  for term in d: 
    ...: ...   index = vocabulary.setdefault(term, len(vocabulary)) 
    ...: ...   indices.append(index) 
    ...: ...   data.append(1) 
    ...: ...  indptr.append(len(indices)) 
    ...:  
In [504]: indptr 
Out[504]: [0, 3, 6] 
In [505]: indices 
Out[505]: [0, 1, 0, 2, 3, 1] 
In [506]: data 
Out[506]: [1, 1, 1, 1, 1, 1] 
In [507]: vocabulary 
Out[507]: {'cruel': 3, 'goodbye': 2, 'hello': 0, 'world': 1} 
In [508]: M = sparse.csr_matrix((data, indices, indptr), dtype=int) 
In [510]: M 
Out[510]: 
<2x4 sparse matrix of type '<class 'numpy.int32'>' 
    with 6 stored elements in Compressed Sparse Row format> 
In [511]: M.A 
Out[511]: 
array([[2, 1, 0, 0], 
     [0, 1, 1, 1]]) 

Les entrées coo ressembleraient:

In [515]: Mc = M.tocoo() 
In [516]: Mc.row 
Out[516]: array([0, 0, 0, 1, 1, 1], dtype=int32) 
In [517]: Mc.col 
Out[517]: array([0, 1, 0, 2, 3, 1], dtype=int32) 

Ainsi, les mêmes travaux d'itération, sauf que nous enregistrons le numéro de ligne dans une liste row:

In [519]: row, col, data = [],[],[] 
In [520]: vocabulary = {} 
In [521]: for i,d in enumerate(docs): 
    ...:  for term in d: 
    ...:   index = vocabulary.setdefault(term, len(vocabulary)) 
    ...:   col.append(index) 
    ...:   data.append(1) 
    ...:   row.append(i) 
    ...:   
In [522]: row 
Out[522]: [0, 0, 0, 1, 1, 1] 
In [523]: col 
Out[523]: [0, 1, 0, 2, 3, 1] 
In [524]: M1 = sparse.coo_matrix((data, (row, col))) 
In [525]: M1 
Out[525]: 
<2x4 sparse matrix of type '<class 'numpy.int32'>' 
    with 6 stored elements in COOrdinate format> 
In [526]: M1.A 
Out[526]: 
array([[2, 1, 0, 0], 
     [0, 1, 1, 1]]) 

'bonjour' se produit deux fois dans la première liste; tous les autres mots apparaissent une fois, ou aucun. vocabulary a le mappage entre les mots et les index de colonne.

Une alternative ferait deux passes. Le premier recueille tous les mots et identifie les uniques - c'est-à-dire, générer vocabulary ou l'équivalent. La seconde construit ensuite la matrice.