如何在大稀疏矩阵中找到非零元素的索引?

时间:2011-09-09 12:12:01

标签: python algorithm r sparse-matrix indices

我有两个sq矩阵(a,b),大小为100000 X 100000.我必须区分这两个矩阵(c = a-b)。结果矩阵'c'是稀疏矩阵。我想找到所有非零元素的索引。我必须多次执行此操作(> 100)。

最简单的方法是使用两个for循环。但这是计算密集型的。你能告诉我任何算法或包/库最好在R / python / c中尽快做到这一点吗?

6 个答案:

答案 0 :(得分:4)

由于你有两个密集矩阵,所以double for循环是你唯一的选择。您根本不需要稀疏矩阵类,因为您只想知道(i,j)的索引列表a[i,j] != b[i,j]

在像R和Python这样的语言中,双循环将表现不佳。我可能会在本机代码中为double for循环编写它,并将索引添加到列表对象中。但毫无疑问,解释代码的向导(即R,Python等)知道有效的方法,而不需要使用本机编码。

答案 1 :(得分:3)

在R中,如果您使用Matrix包和sparseMatrix进行从coordinate list到稀疏矩阵的转换,则可以通过以下方式转换回3列:< / p>

TmpX <- as(M, "dgTMatrix")
X3col <- matrix(c(TmpX@i, TmpX@j, TmpX@val), ncol = 3)

这将为您提供稀疏矩阵中的坐标和值。

根据A和B中非零项的位置,您可能会发现使用坐标列表比使用稀疏矩阵表示(顺便提一下,有数十种稀疏矩阵表示)更好。您可以直接利用矢量化操作,而不是依靠稀疏矩阵包来实现最佳性能。我倾向于在不同语言中使用COO或稀疏矩阵支持之间交替,这取决于我将如何获得感兴趣的算法的最快性能。


更新1:我不知道你的两个矩阵A和B是密集的。因此,在C中找到非零条目的最简单的解决方案就是简单地首先不减去 - 只需比较A和B的条目。逻辑比较应该比减法更快。首先,找到A和B的条目A != B,然后只减去那些条目。接下来,您只需要将A和B中索引的矢量化转换为它们的(row,col)表示。这与matlab的ind2sub和sub2ind类似 - 请查看this R reference进行计算。

答案 2 :(得分:1)

看看numpy它有你要求的一切以及更多!

请参阅this了解稀疏矩阵支持

答案 3 :(得分:1)

您可以使用c.nonzero()方法:

>>> from scipy.sparse import lil_eye
>>> c = lil_eye((4, 10)) # as an example
>>> c
<4x10 sparse matrix of type '<type 'numpy.float64'>'
        with 4 stored elements in LInked List format>
>>> c.nonzero()
(array([0, 1, 2, 3], dtype=int32), array([0, 1, 2, 3], dtype=int32))
>>> import numpy as np
>>> np.ascontiguousarray(c)
array([  (0, 0) 1.0
  (1, 1)        1.0
  (2, 2)        1.0
  (3, 3)        1.0], dtype=object)

您无需计算c矩阵来查找c = a - b中非零元素的索引;你可以做(a != b).nonzero()

>>> a = np.random.random_integers(2, size=(4,4))
>>> b = np.random.random_integers(2, size=(4,4))
>>> (a != b).nonzero()
(array([0, 0, 1, 1, 1, 2, 3]), array([1, 2, 1, 2, 3, 2, 0]))
>>> a - b
array([[ 0,  1,  1,  0],
       [ 0,  1, -1, -1],
       [ 0,  0,  1,  0],
       [-1,  0,  0,  0]])

答案 4 :(得分:1)

此代码少于0.1秒。

m <- matrix(rpois(1000000,0.01),ncol=1000)
m0 <- lapply(seq(NCOL(m)),function(x) which(m[,x] != 0))

编辑: 对于任何大小的稀疏矩阵(适合记忆)。

DATA

library(data.table)

N <- 1e+5
n <- 1e+6

ta <- data.table(r=sample(seq(N), n,replace=TRUE),
                 c=sample(seq(N), n,replace=TRUE),
                 a=sample(1:20,n,replace=TRUE))
tb <- data.table(r=sample(seq(N), n,replace=TRUE),
                 c=sample(seq(N), n,replace=TRUE),
                 b=sample(1:20,n,replace=TRUE))
setkey(ta,r,c)
setkey(tb,r,c)

CODE

system.time(tw <- ta[tb][is.na(a)|is.na(b)|(a-b != 0),list(r=r,c=c)])

答案 5 :(得分:1)

我还没有计时,但最简单的代码是

all.indices<- which (C>0, arr.ind=T)