Создание и обновление разреженной матрицы в python с использованием scipy
Я пытаюсь создать и обновить разреженную матрицу при чтении данных из файла.
Матрица имеет размер 100000X40000
Каков наиболее эффективный способ обновления нескольких записей разреженной матрицы?
в частности, мне нужно увеличивать каждую запись на 1.
Скажем, у меня есть индексы строк [2, 236, 246, 389, 1691]
и индексы столбцов [117, 3, 34, 2757, 74, 1635, 52]
поэтому все следующие записи должны быть увеличены на единицу:
(2,117) (2,3) (2,34) (2,2757) ...
(236,117) (236,3) (236, 34) (236,2757) ...
и т.д.
Я уже использую lil_matrix
, поскольку он дал мне предупреждение для использования, когда я пытался обновить одну запись.
Формат
lil_matrix
уже не поддерживает множественное обновление.
matrix[1:3,0] += [2,3]
дает мне недопустимую ошибку.
Я могу сделать это наивно, увеличивая каждую запись по отдельности. Мне было интересно, есть ли какой-нибудь лучший способ сделать это, или лучше разреженную матричную реализацию, которую я могу использовать.
Мой компьютер также является средним i5-машиной с 4 ГБ оперативной памяти, поэтому я должен быть осторожным, чтобы не взорвать его:)
Ответы
Ответ 1
Создание второй матрицы с 1
в ваших новых координатах и добавление ее к существующему можно сделать следующим образом:
>>> 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>
Ответ 2
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))
Я думаю, что он работает хорошо и не нуждается в цикле. Я непосредственно следую за doc
<100000x40000 sparse matrix of type '<type 'numpy.int32'>'
with 35 stored elements in COOrdinate format>
Ответ 3
Этот ответ расширяет комментарий @behzad.nouri. Чтобы увеличить значения в "внешнем продукте" ваших списков индексов строк и столбцов, просто создайте их как массивы numpy, настроенные для трансляции. В этом случае это означает, что строки помещаются в столбец. Например,
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]])