从python中给定大型稀疏矩阵的不同行的操作创建一个新的稀疏矩阵

时间:2016-12-11 14:30:17

标签: python numpy scipy sparse-matrix

让我们说,S是大scipy-csr矩阵(稀疏)和带密钥的字典D - > S&中行向量A的索引(位置)。值 - > S中其他行向量l的所有索引(位置)的列表。对于l中的每个行向量,你减去A并得到新的向量,它只是要在新的稀疏矩阵中更新的新行向量。

表格字典 - > { 1:[4,5,...,63] } 然后必须用....创建一个新的稀疏矩阵。

new_row_vector_1 - > S_vec 1 - S_vec 4

new_row_vector_2 - > S_vec 1 - S_vec 5

new_row_vector_n - > S_vec 1 - S_vec 63

其中S_vecX是矩阵S的第X行向量

Check out the pictorial explanation of the above statements

Numpy示例:

>>> import numpy as np
>>> s = np.array([[1,5,3,4],[3,0,12,7],[5,6,2,4],[4,6,6,4],[7,12,5,67]])
>>> s
array([[ 1,  5,  3,  4],
       [ 3,  0, 12,  7],
       [ 5,  6,  2,  4],
       [ 4,  6,  6,  4],
       [ 7, 12,  5, 67]])
>>> index_dictionary = {0: [2, 4], 1: [3, 4], 2: [1], 3: [1, 2], 4: [1, 3, 2]} 
>>> n = np.zeros((10,4)) #sum of all lengths of values in index_dictionary would be the number of rows for the new array(n) and columns remain the same as s.
>>> n
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])
>>> idx = 0
>>> for index in index_dictionary:
...     for k in index_dictionary[index]:
...             n[idx] = s[index]-s[k]
...             idx += 1
... 
>>> n
array([[ -4.,  -1.,   1.,   0.],
       [ -6.,  -7.,  -2., -63.],
       [ -1.,  -6.,   6.,   3.],
       [ -4., -12.,   7., -60.],
       [  2.,   6., -10.,  -3.],
       [  1.,   6.,  -6.,  -3.],
       [ -1.,   0.,   4.,   0.],
       [  4.,  12.,  -7.,  60.],
       [  3.,   6.,  -1.,  63.],
       [  2.,   6.,   3.,  63.]])

n是我想要的。

1 个答案:

答案 0 :(得分:0)

以下是我认为你想要做的简单演示:

首先是numpy数组版本:

In [619]: arr=np.arange(12).reshape(4,3)
In [620]: arr[[1,0,2,3]]-arr[0] 
Out[620]: 
array([[3, 3, 3],
       [0, 0, 0],
       [6, 6, 6],
       [9, 9, 9]])

现在是稀疏的等价物:

In [622]: M=sparse.csr_matrix(arr)

csr实现了行索引:

In [624]: M[[1,0,2,3]]
Out[624]: 
<4x3 sparse matrix of type '<class 'numpy.int32'>'
    with 11 stored elements in Compressed Sparse Row format>
In [625]: M[[1,0,2,3]].A
Out[625]: 
array([[ 3,  4,  5],
       [ 0,  1,  2],
       [ 6,  7,  8],
       [ 9, 10, 11]], dtype=int32)

但不是广播:

In [626]: M[[1,0,2,3]]-M[0]
 ....
ValueError: inconsistent shapes

所以我们可以使用明确的广播形式

In [627]: M[[1,0,2,3]]-M[[0,0,0,0]]  # or M[[0]*4]
Out[627]: 
<4x3 sparse matrix of type '<class 'numpy.int32'>'
    with 9 stored elements in Compressed Sparse Row format>
In [628]: _.A
Out[628]: 
array([[3, 3, 3],
       [0, 0, 0],
       [6, 6, 6],
       [9, 9, 9]], dtype=int32)

这可能不是最快或最有效的,但它是一个开始。

我在之前的SO问题中发现M[[1,0,2,3]]索引是使用矩阵乘法执行的,在本例中相当于:

idxM = sparse.csr_matrix(([1,1,1,1],([0,1,2,3],[1,0,2,3])),(4,4))
M1 = idxM * M

Sparse matrix slicing using list of int

所以我的差异表达式需要2次这样的乘法以及减法。

我们可以尝试逐行迭代,并从结果中构建一个新矩阵,但不能保证它会更快。根据阵列的不同,转换为密集和后退可能会更快。

=================

我可以想象将两种方法应用到字典中。

一个是迭代字典(什么顺序?),为每个键执行此差异,在列表中收集结果(稀疏矩阵列表),并使用sparse.bmat将它们连接成一个矩阵。

另一种方法是收集两个索引列表,并将上述索引差异仅应用一次。

In [8]: index_dictionary = {0: [2, 4], 1: [3, 4], 2: [1], 3: [1, 2], 4: [1, 3, 2]} 
In [10]: alist=[]
    ...: for index in index_dictionary:
    ...:     for k in index_dictionary[index]:
    ...:         alist.append((index, k))       
In [11]: idx = np.array(alist)
In [12]: idx
Out[12]: 
array([[0, 2],
       [0, 4],
       [1, 3],
       [1, 4],
       [2, 1],
       [3, 1],
       [3, 2],
       [4, 1],
       [4, 3],
       [4, 2]])

应用于您的密集s

In [15]: s = np.array([[1,5,3,4],[3,0,12,7],[5,6,2,4],[4,6,6,4],[7,12,5,67]])
In [16]: s[idx[:,0]]-s[idx[:,1]]
Out[16]: 
array([[ -4,  -1,   1,   0],
       [ -6,  -7,  -2, -63],
       [ -1,  -6,   6,   3],
       [ -4, -12,   7, -60],
       [  2,   6, -10,  -3],
       [  1,   6,  -6,  -3],
       [ -1,   0,   4,   0],
       [  4,  12,  -7,  60],
       [  3,   6,  -1,  63],
       [  2,   6,   3,  63]])

和稀疏的等价物

In [19]: arr= sparse.csr_matrix(s)
In [20]: arr
Out[20]: 
<5x4 sparse matrix of type '<class 'numpy.int32'>'
    with 19 stored elements in Compressed Sparse Row format>
In [21]: res=arr[idx[:,0]]-arr[idx[:,1]]
In [22]: res
Out[22]: 
<10x4 sparse matrix of type '<class 'numpy.int32'>'
    with 37 stored elements in Compressed Sparse Row format>