scipy.sparse.coo_matrix如何快速查找所有零列,填充1并进行规范化

时间:2016-09-25 06:04:13

标签: python numpy scipy linear-algebra sparse-matrix

对于矩阵,我想找到全零的列并用1填充,然后按列对矩阵进行标准化。我知道如何用np.arrays

做到这一点
9721df798198##-1
9721df798198##-1-2
9721df798198##-1-2-4
9721df798198##-1-2-4-9
9721df798198##-1-2-4-9-14-16
9721df798198##-1-2-4-9-14-16-26
9721df798198##-1-2-4-9-14-16-26-27
9721df798198##-1-2-4-9-14-16-26-27-28
9721df798198##-1-2-4-9-14-16-26-27-28-29
9721df798198##-1-2-4-9-14-16-112
9721df798198##-1-2-4-9-14-16-112-113
9721df798198##-1-2-4-9-14-16-112-113-114

但是当矩阵处于scipy.sparse.coo.coo_matrix形式时,我怎么能做同样的事情,而不将其转换回np.arrays。我怎样才能达到同样的目的呢?

1 个答案:

答案 0 :(得分:2)

使用lil格式并使用行而不是列时,这将更容易:

In [1]: from scipy import sparse
In [2]: A=np.array([[0,0,0,0,0],[0,0,1,0,0],[1,0,0,1,0],[0,0,0,0,1],[1,0,0,0,0]])
In [3]: A
Out[3]: 
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [1, 0, 0, 1, 0],
       [0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0]])
In [4]: At=A.T                # switch to work with rows

In [5]: M=sparse.lil_matrix(At)

现在很明显哪一行是全零

In [6]: M.data
Out[6]: array([[1, 1], [], [1], [1], [1]], dtype=object)
In [7]: M.rows
Out[7]: array([[2, 4], [], [1], [2], [3]], dtype=object)

lil格式允许我们填充该行:

In [8]: M.data[1]=[1,1,1,1,1]
In [9]: M.rows[1]=[0,1,2,3,4]
In [10]: M.A
Out[10]: 
array([[0, 0, 1, 0, 1],
       [1, 1, 1, 1, 1],
       [0, 1, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 1, 0]], dtype=int32)

我本可以使用M[1,:]=np.ones(5,int)

coo格式非常适合从data/row/col数组创建数组,但不会实现索引或数学。它必须转换为csr。并且csc用于面向列的内容。

我填写的行在csr格式中并不那么明显:

In [14]: Mc=M.tocsr()
In [15]: Mc.data
Out[15]: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int32)
In [16]: Mc.indices
Out[16]: array([2, 4, 0, 1, 2, 3, 4, 1, 2, 3], dtype=int32)
In [17]: Mc.indptr
Out[17]: array([ 0,  2,  7,  8,  9, 10], dtype=int32)

另一方面,在这种格式下,规范化可能更容易。

In [18]: Mc.sum(axis=1)
Out[18]: 
matrix([[2],
        [5],
        [1],
        [1],
        [1]], dtype=int32)
In [19]: Mc/Mc.sum(axis=1)
Out[19]: 
matrix([[ 0. ,  0. ,  0.5,  0. ,  0.5],
        [ 0.2,  0.2,  0.2,  0.2,  0.2],
        [ 0. ,  1. ,  0. ,  0. ,  0. ],
        [ 0. ,  0. ,  1. ,  0. ,  0. ],
        [ 0. ,  0. ,  0. ,  1. ,  0. ]])

请注意,它已将稀疏矩阵转换为密集矩阵。 sum密集,涉及稀疏和密集的数学通常会产生密集。

我必须使用更多的计算来保持稀疏状态:

In [27]: Mc.multiply(sparse.csr_matrix(1/Mc.sum(axis=1)))
Out[27]: 
<5x5 sparse matrix of type '<class 'numpy.float64'>'
    with 10 stored elements in Compressed Sparse Row format>

以下是使用csc格式(A

执行此操作的方法
In [40]: Ms=sparse.csc_matrix(A)
In [41]: Ms.sum(axis=0)
Out[41]: matrix([[2, 0, 1, 1, 1]], dtype=int32)

使用sum查找全零列。显然,如果列具有负值并且碰巧总和为0,则可能是错误的。如果这是一个问题,我可以看到制作矩阵的副本,其中所有data值都替换为1.

In [43]: Ms[:,1]=np.ones(5,int)[:,None]
/usr/lib/python3/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csc_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)
In [44]: Ms.A
Out[44]: 
array([[0, 1, 0, 0, 0],
       [0, 1, 1, 0, 0],
       [1, 1, 0, 1, 0],
       [0, 1, 0, 0, 1],
       [1, 1, 0, 0, 0]])

如果您反复进行此类更改,则警告更重要。注意我必须调整LHS阵列的尺寸。根据全零列的数量,此操作可以显着改变矩阵的稀疏性。

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

我可以使用{<1}} col格式搜索缺失值:

coo

然后,我可以在此In [69]: Mo=sparse.coo_matrix(A) In [70]: Mo.col Out[70]: array([2, 0, 3, 4, 0], dtype=int32) In [71]: Mo.col==np.arange(Mo.shape[1])[:,None] Out[71]: array([[False, True, False, False, True], [False, False, False, False, False], [ True, False, False, False, False], [False, False, True, False, False], [False, False, False, True, False]], dtype=bool) In [72]: idx = np.nonzero(~(Mo.col==np.arange(Mo.shape[1])[:,None]).any(axis=1))[0] In [73]: idx Out[73]: array([1], dtype=int32) 添加一列1,其中包含:

idx

如上所述它仅适用于一列,但可以推广到几列。我还创建了一个新矩阵,而不是更新In [75]: N=Mo.shape[0] In [76]: data = np.concatenate([Mo.data, np.ones(N,int)]) In [77]: row = np.concatenate([Mo.row, np.arange(N)]) In [78]: col = np.concatenate([Mo.col, np.ones(N,int)*idx]) In [79]: Mo1 = sparse.coo_matrix((data,(row, col)), shape=Mo.shape) In [80]: Mo1.A Out[80]: array([[0, 1, 0, 0, 0], [0, 1, 1, 0, 0], [1, 1, 0, 1, 0], [0, 1, 0, 0, 1], [1, 1, 0, 0, 0]]) 。但这个就地也似乎也有效:

Mo

规范化仍然需要Mo.data,Mo.col,Mo.row = data,col,row 转换,但我认为csr可以为您隐藏。

sparse

即使我采取了保持稀疏性质的额外工作,我仍然得到一个In [87]: Mo1/Mo1.sum(axis=0) Out[87]: matrix([[ 0. , 0.2, 0. , 0. , 0. ], [ 0. , 0.2, 1. , 0. , 0. ], [ 0.5, 0.2, 0. , 1. , 0. ], [ 0. , 0.2, 0. , 0. , 1. ], [ 0.5, 0.2, 0. , 0. , 0. ]]) 矩阵:

csr

Find all-zero columns in pandas sparse matrix

有关查找0列的更多方法。结果In [89]: Mo1.multiply(sparse.coo_matrix(1/Mo1.sum(axis=0))) Out[89]: <5x5 sparse matrix of type '<class 'numpy.float64'>' with 10 stored elements in Compressed Sparse Row format> 对于大Mo.col==np.arange(Mo.shape[1])[:,None]来说太慢了。使用Mo的测试要好得多。

np.in1d