我有两个sq矩阵(a,b),大小为100000 X 100000.我必须区分这两个矩阵(c = a-b)。结果矩阵'c'是稀疏矩阵。我想找到所有非零元素的索引。我必须多次执行此操作(> 100)。
最简单的方法是使用两个for循环。但这是计算密集型的。你能告诉我任何算法或包/库最好在R / python / c中尽快做到这一点吗?
答案 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)
答案 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)