(稀疏)2D numpy 数组的每行/列的快速非零索引

计算科学 Python 稀疏矩阵 scipy 麻木的
2021-12-10 02:46:26

我正在寻找最快的方法来获取每行和每列二维数组的非零索引列表。以下是一段工作代码:

preds = [matrix[:,v].nonzero()[0] for v in range(matrix.shape[1])]
descs = [matrix[v].nonzero()[0] for v in range(matrix.shape[0])]

示例输入:

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

示例输出

preds = [array([1, 2, 3]), array([2, 3]), array([3]), array([], dtype=int64)]
descs = [array([], dtype=int64), array([0]), array([0, 1]), array([0, 1, 2])]

(这些列表称为 preds 和 descs,因为当矩阵被解释为邻接矩阵时,它们指的是 DAG 中的前辈和后辈,但这对于问题来说不是必需的。)

我想知道这是否可以通过某种稀疏矩阵(CSR、CSC、COO 等)来实现,scipy.sparse但我对它们不熟悉并且没有得到它的工作。如果存在更快的选项,我不一定需要使用这些类型。

时序示例: 出于时序目的,以下矩阵是一个很好的代表:

test_matrix = np.zeros(shape=(4096,4096),dtype=np.float32)
for k in range(16):
    test_matrix[256*(k+1):256*(k+2),256*k:256*(k+1)]=1

谢谢你。

背景:在我的代码中,这两行代码占用了 4000x4000 矩阵的 75% 的时间,而随后的拓扑排序和 DP 算法只占用了本季度的剩余时间。如果有人知道如何更有效地做到这一点,将不胜感激。大约 5% 的矩阵具有非零值。

(根据建议,我将问题移至此处:https ://stackoverflow.com/questions/62065793/fast-nonzero-indices-per-row-column-for-sparse-2d-numpy-array 包含几个有用的答案

1个回答

理想情况下,您应该已经拥有稀疏矩阵数据结构中的矩阵。但是对于这个例子,我们可以通过

In [31]: M = scipy.sparse.coo_matrix(np.array([[0,0,0,0],[1,0,0,0],[1,1,0,0],[1,1,1,0]]))

然后你可以做

In [32]: Mcsr = M.tocsr() 

In [33]: np.split(Mcsr.indices, Mcsr.indptr)         
Out[33]: 
[array([], dtype=int32),
 array([], dtype=int32),
 array([0], dtype=int32),
 array([0, 1], dtype=int32),
 array([0, 1, 2], dtype=int32),
 array([], dtype=int32)]

得到descs. 相似地,

In [34]: Mcsc = M.tocsc() 

In [35]: np.split(Mcsc.indices, Mcsc.indptr)        
Out[35]: 
[array([], dtype=int32),
 array([1, 2, 3], dtype=int32),
 array([2, 3], dtype=int32),
 array([3], dtype=int32),
 array([], dtype=int32),
 array([], dtype=int32)]

preds. 我不知道这在实践中是否更有效。