web-dev-qa-db-fra.com

Construire et mettre à jour une matrice clairsemée en python en utilisant scipy

J'essaie de créer et de mettre à jour une matrice clairsemée en lisant les données du fichier. La matrice est de taille 100000X40000

Quelle est la manière la plus efficace de mettre à jour plusieurs entrées de la matrice clairsemée? en particulier, je dois incrémenter chaque entrée de 1.

Disons que j'ai des indices de ligne [2, 236, 246, 389, 1691]

et indices de colonne [117, 3, 34, 2757, 74, 1635, 52]

toutes les entrées suivantes doivent donc être incrémentées d'une unité:

(2,117) (2,3) (2,34) (2,2757) ...

(236,117) (236,3) (236, 34) (236,2757) ...

etc.

J'utilise déjà lil_matrix Car il m'a donné un avertissement à utiliser pendant que j'essayais de mettre à jour une seule entrée.

Le format lil_matrix Ne prend déjà pas en charge les mises à jour multiples. matrix[1:3,0] += [2,3] Me donne une erreur non implémentée.

Je peux le faire naïvement, en incrémentant chaque entrée individuellement. Je me demandais s'il y avait une meilleure façon de le faire, ou une meilleure implémentation de matrice clairsemée que je peux utiliser.

Mon ordinateur est également une machine i5 moyenne avec 4 Go de RAM, donc je dois faire attention à ne pas le faire exploser :)

21
syllogismos

Création d'une deuxième matrice avec 1s dans vos nouvelles coordonnées et en les ajoutant à celles existantes est une façon possible de le faire:

>>> import scipy.sparse as sps
>>> shape = (1000, 2000)
>>> rows, cols = 1000, 2000
>>> sps_acc = sps.coo_matrix((rows, cols)) # empty matrix
>>> for j in xrange(100): # add 100 sets of 100 1's
...     r = np.random.randint(rows, size=100)
...     c = np.random.randint(cols, size=100)
...     d = np.ones((100,))
...     sps_acc = sps_acc + sps.coo_matrix((d, (r, c)), shape=(rows, cols))
... 
>>> sps_acc
<1000x2000 sparse matrix of type '<type 'numpy.float64'>'
    with 9985 stored elements in Compressed Sparse Row format>
12
Jaime
import scipy.sparse

rows = [2, 236, 246, 389, 1691]
cols = [117, 3, 34, 2757, 74, 1635, 52]
prod = [(x, y) for x in rows for y in cols] # combinations
r = [x for (x, y) in prod] # x_coordinate
c = [y for (x, y) in prod] # y_coordinate
data = [1] * len(r)
m = scipy.sparse.coo_matrix((data, (r, c)), shape=(100000, 40000))

Je pense que cela fonctionne bien et n'a pas besoin de boucles. Je suis directement le doc

<100000x40000 sparse matrix of type '<type 'numpy.int32'>'
    with 35 stored elements in COOrdinate format>
7
Ray

Cette réponse élargit le commentaire de @ behzad.nouri. Pour incrémenter les valeurs au "produit externe" de vos listes d'indices de lignes et de colonnes, créez-les simplement en tant que tableaux numpy configurés pour la diffusion. Dans ce cas, cela signifie mettre les lignes dans une colonne. Par exemple,

In [59]: a = lil_matrix((4,4), dtype=int)

In [60]: a.A
Out[60]: 
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

In [61]: rows = np.array([1,3]).reshape(-1, 1)

In [62]: rows
Out[62]: 
array([[1],
       [3]])

In [63]: cols = np.array([0, 2, 3])

In [64]: a[rows, cols] += np.ones((rows.size, cols.size))

In [65]: a.A
Out[65]: 
array([[0, 0, 0, 0],
       [1, 0, 1, 1],
       [0, 0, 0, 0],
       [1, 0, 1, 1]])

In [66]: rows = np.array([0, 1]).reshape(-1,1)

In [67]: cols = np.array([1, 2])

In [68]: a[rows, cols] += np.ones((rows.size, cols.size))

In [69]: a.A
Out[69]: 
array([[0, 1, 1, 0],
       [1, 1, 2, 1],
       [0, 0, 0, 0],
       [1, 0, 1, 1]])
5
Warren Weckesser