首页 > 解决方案 > 从 SciPy 稀疏矩阵获取左、右、上、下非零邻居

问题描述

假设我有一个 2D SciPy 稀疏矩阵:

import numpy as np
from scipy.sparse import csc_matrix

arr = np.array([[0, 0, 1, 0, 1],
                [1, 0, 0, 1, 0],
                [0, 1, 1, 0, 0],
                [1, 0, 0, 1, 0],
                [0, 1, 0, 0, 0],
               ])

csc = csc_matrix(arr)

对于矩阵中的每个非零元素,我想创建四个新的稀疏矩阵,其中包含与下一个最近的 Left、Right、Up 和 Down 非零邻居对应的索引。末端的元素可以有环绕的邻居(想想水平和垂直方向的圆形双向链表或环形)。如果一个元素是其行/列中唯一的非零元素,则相应的索引将指向它自己。此外,由于索引可以具有零值(当引用第一行或第一列时)并且与自然为零的元素无法区分,我们将这些零索引设置为 -1 以消除实际索引与零元素的歧义。

对于上面的矩阵,密集的左矩阵和下矩阵如下所示:

left = np.array([[0, 0, 4,  0, 2],
                 [3, 0, 0, -1, 0],
                 [0, 2, 1,  0, 0],
                 [3, 0, 0, -1, 0],
                 [0, 1, 0,  0, 0],
                ])

down = np.array([[0, 0,  2, 0, -1],
                 [3, 0,  0, 3,  0],
                 [0, 4, -1, 0,  0],
                 [1, 0,  0, 1,  0],
                 [0, 2,  0, 0,  0],
                ])

请记住,索引值为 -1 的元素实际上是对索引零的引用。当然,我需要将这些矩阵设为稀疏矩阵形式,因为我的真实矩阵太大且太稀疏,无法放入内存。

标签: pythonnumpymatrixscipysparse-matrix

解决方案


这是一种可能的方法来做左边的邻居。它不是特别有效,但如果整个矩阵中没有很多非零条目,它可能工作得很好。您可以通过获取每行的非零条目并且只计算j[i==row]一次来稍微优化它。

请注意,我只是将索引上移一,而不是设置0-1.

i,j = csc.nonzero()
ind = sp.sparse.csc_matrix(csc.shape,dtype='int')
for row in range(csc.shape[0]):
    ind[row,j[i==row]] = np.roll(j[i==row]+1,1)

ind.A = array([[0, 0, 5, 0, 3],
   [4, 0, 0, 1, 0],
   [0, 3, 2, 0, 0],
   [4, 0, 0, 1, 0],
   [0, 2, 0, 0, 0]])

推荐阅读