2013-12-14 2 views
20

Я пытаюсь создать и обновить разреженную матрицу при чтении данных из файла. Матрица размером 100000X40000Создание и обновление разреженной матрицы в python с использованием scipy

Что является наиболее эффективным способом обновления нескольких записей разреженной матрицы? конкретно мне нужно увеличивать каждую запись на 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

он работает для 'lil_matrix' если правая рука' numpy' массив сопоставления формы, как 'А [1: 3, 0] + = np.array ([[2], [3]]) ' –

+0

Да, я понял, что часть. но есть ли у вас какие-либо предложения по моей конкретной проблеме? например, с учетом индексов строк и индексов столбцов, я хочу увеличить все комбинации, как указано в вопросе. – syllogismos

ответ

12

Создание второй матрицы с 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> 
5
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> 
+1

cols_iter = цикл (cols), r, c = zip (* [(x, cols_iter.next()) для x в строках]), а data = np.ones (len (r)) делает это немного быстрее – M4rtini

+0

- это эффективный способ сделать это? Я имею в виду, могу ли я добавить это в свою основную матрицу на каждой итерации, на каждой итерации я получаю новые массивы строк и столбцов. – syllogismos

+0

@syllogismos Я так думаю, по документу, так создается новая разреженная матрица. Должно быть, по крайней мере, быстрее, чем цикл. – Ray

4

Этот ответ расширяет замечание @ 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]]) 
+0

Я доволен этим решением, так как он позволяет вам обновлять одну строку за раз в разреженной lil_matrix. –

Смежные вопросы