我正在寻找一种最快的方法来获取一个二维数组的每行和每列的非零索引列表。下面是一段代码:
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])]
(The列表被称为预测和描述,因为当矩阵被解释为邻接矩阵时,它们指的是DAG中的前趋和后代,但这对问题来说不是必需的。)
- 时间示例:**出于时间目的,以下矩阵是一个很好的代表:
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%的值是非零的,所以稀疏矩阵的解决方案可能是适用的。
谢谢你。
(On建议也张贴在这里:https://scicomp.stackexchange.com/questions/35242/fast-nonzero-indices-per-row-column-for-sparse-2d-numpy-array还有一些答案,我将在评论中提供时间。此链接包含一个可接受的答案,速度是原来的两倍。)
3条答案
按热度按时间vwoqyblh1#
如果你有足够的动力,Numba可以做出惊人的事情。下面是你所需要的逻辑的快速实现。简单地说,它计算
np.nonzero()
的等价物,但它同时包含了稍后将索引分派成你所需要的格式的信息。这些信息是受sparse.csr.indptr
和sparse.csc.indptr
的启发而产生的。根据www.example.com上的@hpaulj答案(
row_col_idx_sparse_lil()
)和@knl答案(row_col_idx_sparse_coo()
),与您的方法(下面的row_col_idx_sep()
)以及其他一些方法相比:scicomp.stackexchange.com (row_col_idx_sparse_coo()
):一个一个一个一个一个x一个一个二个一个x一个一个三个一个x一个一个x一个四个一个
对于使用生成的输入:
我们会得到(您的
test_matrix
具有大约0.06的非零密度):这表明它的速度接近最快的基于
scipy.sparse
的方法的两倍。ufj5ltwl2#
数据存在于整个数组
nonzero
中,只是没有分解为每行/列数组:可以将
array([1, 2, 2, 3, 3, 3])
分解为基于另一个数组的子列表[1,2,3],[2,3],[3],[]
,但这可能需要一些时间来解决逻辑问题,而且不能保证它会比行/列迭代更快。逻辑运算可以将布尔数组缩减为列或行,给出出现非零值的行或列,但也不是不规则的:
scipy.sparse
lil
确实会生成所需的数据:但是定时可能并不比行或列迭代更好。
js4nwp543#
例如,也可以使用
np.bincount()
来执行此操作需要注意的一点是,矩阵中的行/列是否全为零: