Python 在scipy稀疏矩阵上掩码为真时,将元素设置为零的有效方法

Python 在scipy稀疏矩阵上掩码为真时,将元素设置为零的有效方法,python,matrix,scipy,sparse-matrix,mask,Python,Matrix,Scipy,Sparse Matrix,Mask,我有两个scipy_sparse_csr_矩阵'a'和scipy_sparse_csr_矩阵(布尔)'mask',我想将'a'的元素设置为零,其中mask的元素为真 比如说 >>>a <3x3 sparse matrix of type '<type 'numpy.int32'>' with 4 stored elements in Compressed Sparse Row format> >>>a.todense() mat

我有两个scipy_sparse_csr_矩阵'a'和scipy_sparse_csr_矩阵(布尔)'mask',我想将'a'的元素设置为零,其中mask的元素为真

比如说

>>>a
<3x3 sparse matrix of type '<type 'numpy.int32'>'
    with 4 stored elements in Compressed Sparse Row format>
>>>a.todense()
matrix([[0, 0, 3],
        [0, 1, 5],
        [7, 0, 0]])

>>>mask
<3x3 sparse matrix of type '<type 'numpy.bool_'>'
    with 4 stored elements in Compressed Sparse Row format>
>>>mask.todense()
matrix([[ True, False,  True],
        [False, False,  True],
        [False,  True, False]], dtype=bool)

但我认为上述操作效率低下。由于“a”和“掩码”的实际形状为67108864×2000000,因此在高规格服务器(64核Xeon cpu,512GB内存)上执行这些操作需要几秒钟。例如,“a”大约有30000000个非零元素,“mask”大约有1800000个非零(真)元素,那么上述操作大约需要2秒钟

有没有更有效的方法

情况如下

  • a、 getnnz()!=mask.getnnz()
  • a、 shape=mask.shape
  • 谢谢

    其他方式(已尝试)


    我最初的印象是,这种乘减法是合理的。通常,
    sparse
    代码将操作实现为某种乘法,即使密集等价物使用更直接的方法。行或列上的稀疏和使用矩阵与1的适当行或列矩阵相乘。偶数行或列索引使用矩阵乘法(至少在
    csr
    格式上)

    有时,我们可以通过直接使用矩阵属性(
    data
    index
    indptr
    )来改进操作。但这需要更多的思考和实验

    对于密集阵列,我的第一次尝试是

    In [611]: a.A*~(mask.A)
    Out[611]: 
    array([[0, 0, 0],
           [0, 1, 0],
           [7, 0, 0]], dtype=int32)
    
    但是没有一种直接的方法可以对稀疏矩阵执行
    not
    。如果
    mask
    确实稀疏,那么
    ~mask
    就不会稀疏。在您的示例中,
    mask
    有4个真项,5个假项,因此密集版本也可以:

    In [612]: nmask=sparse.csr_matrix(~(mask.A))
    In [615]: a.multiply(nmask)
    Out[615]: 
    <3x3 sparse matrix of type '<class 'numpy.int32'>'
        with 2 stored elements in Compressed Sparse Row format>
    
    这也适用于稀疏的

    In [622]: a2=a.copy()
    In [624]: a2[mask]
    Out[624]: matrix([[0, 3, 5, 0]], dtype=int32)
    In [625]: a2[mask]=0
    /usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
      SparseEfficiencyWarning)
    In [626]: a2
    Out[626]: 
    <3x3 sparse matrix of type '<class 'numpy.int32'>'
        with 6 stored elements in Compressed Sparse Row format>
    
    有趣的是,
    al[mask]
    仍然是稀疏的,而as
    a[mask]
    是密集的。这两种格式使用不同的索引方法

    在某种程度上的稀疏性,可能值得迭代
    掩码
    的真(非零)元素,将
    a
    的相应项直接设置为零


    我不会猜测这些方法的相对速度。这需要在真实的数据上进行测试。

    如何比较
    a
    mask
    nnz
    ?除了不一样。两个人都一样稀少吗?谢谢你的回答,@hpaulj!很抱歉把你弄糊涂了。条件1仅表示“掩码的非零(假)元素数与a的元素数不同”。正如您所说,我无法将~应用于矩阵,因为实际矩阵的形状太大。我尝试了一个[mask]=0,但花了一分钟。我刚想到使用.data/消去0来搜索你的答案(添加到问题的最后)。我将在周一对实际数据进行测试。谢谢我在实际数据上尝试了新方法,但它花费的时间是乘法方法的两倍。我并不太惊讶。
    a.data*=~np.array(mask[a.astype(np.bool)]).flatten();a.eliminate_zeros() #This takes twice the time longer than above method.
    
    In [611]: a.A*~(mask.A)
    Out[611]: 
    array([[0, 0, 0],
           [0, 1, 0],
           [7, 0, 0]], dtype=int32)
    
    In [612]: nmask=sparse.csr_matrix(~(mask.A))
    In [615]: a.multiply(nmask)
    Out[615]: 
    <3x3 sparse matrix of type '<class 'numpy.int32'>'
        with 2 stored elements in Compressed Sparse Row format>
    
    In [618]: a1=a.A
    In [619]: a1[mask.A]=0
    
    In [622]: a2=a.copy()
    In [624]: a2[mask]
    Out[624]: matrix([[0, 3, 5, 0]], dtype=int32)
    In [625]: a2[mask]=0
    /usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
      SparseEfficiencyWarning)
    In [626]: a2
    Out[626]: 
    <3x3 sparse matrix of type '<class 'numpy.int32'>'
        with 6 stored elements in Compressed Sparse Row format>
    
    In [628]: a2.eliminate_zeros()
    In [629]: a2
    Out[629]: 
    <3x3 sparse matrix of type '<class 'numpy.int32'>'
        with 2 stored elements in Compressed Sparse Row format>
    
    In [638]: al=a.tolil()
    In [639]: al[mask]
    Out[639]: 
    <1x4 sparse matrix of type '<class 'numpy.int32'>'
        with 2 stored elements in LInked List format>
    In [640]: al[mask]=0
    In [641]: al
    Out[641]: 
    <3x3 sparse matrix of type '<class 'numpy.int32'>'
        with 2 stored elements in LInked List format>