将稀疏矩阵进行R二分化

4

我有一个大的500x53380的稀疏矩阵,想将其二分化。我尝试使用sna包中的“event2dichot”,但没有成功,因为它需要邻接矩阵或网络对象。

我还尝试编写了一个简单的算法:

for ( i in 1:500)
for (j in 1:53380)
if (matrix[i,j]>0) matrix[i,j]=1

这似乎是有效的,但由于矩阵非常大,至少需要几个小时,迄今为止仍在计算中,因此我正在寻求帮助!

您知道完成此任务的更好方法或技巧吗?

谢谢大家。


+1 我刚学会了“二分”的意思 :) - Prasad Chalasani
4个回答

3
尽管你的问题涉及稀疏矩阵,但我认为你的代码实际上描述了一个标准矩阵。
如果是这样的话,你可以在几秒钟内处理一个500x53380的矩阵。以下代码利用了矩阵在R中以向量形式存储的事实。这意味着你可以在整个矩阵上应用单个向量函数。唯一需要注意的是之后必须恢复矩阵的维度。
以下是一个较小矩阵的示例:
mr <- 5
mc <- 8

mat <- matrix(round(rnorm(mr*mc), 3), nrow=mr)
mat

       [,1]   [,2]   [,3]   [,4]   [,5]   [,6]   [,7]   [,8]
[1,] -1.477  1.773  1.630 -0.152  1.054  0.057 -1.260  0.999
[2,] -1.863 -0.312 -0.221 -0.102  0.892 -1.255  0.996 -0.193
[3,] -0.364 -0.059  2.317  1.156  0.893  0.225  0.392 -1.986
[4,] -1.123 -0.661  0.070  0.032  0.019 -1.763 -0.205  0.951
[5,] -0.111 -3.112 -0.970 -0.794 -1.372 -0.119  1.291 -0.680

mydim <- dim(mat)
mat[mat>0] <- 1
mat[mat<0] <- 0
dim(mat) <- mydim
mat

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    1    1    0    1    1    0    1
[2,]    0    0    0    0    1    0    1    0
[3,]    0    0    1    1    1    1    1    0
[4,]    0    0    1    1    1    0    0    1
[5,]    0    0    0    0    0    0    1    0

重复以上过程处理一个500x53380的矩阵需要大约12秒钟完成,这是在我的机器上测试得出的。
mr <- 500
mc <- 53380

system.time({
  mat <- matrix(round(rnorm(mr*mc), 3), nrow=mr)
  mydim <- dim(mat)
  mat[mat>0] <- 1
  mat[mat<0] <- 0
  dim(mat) <- mydim
})

   user  system elapsed 
  12.25    0.42   12.88 

这太棒了。我现在意识到我刚刚浪费了几个小时 :) 我希望我早点来这里写。谢谢。我可以采取哪些步骤来学习这样的技巧,有没有相关文档或者这是我在前进中必须找出的东西?再次感谢。 - dave
@user808562,这实际上在《R手册介绍》中有描述。http://cran.r-project.org/doc/manuals/R-intro.html#Index-matrices - Andrie

2

思考向量化,只使用索引。例如:

mat <- matrix(0, nrow = 500, ncol = 53380)
set.seed(7)
fill <- sample(500*53380, 10000)
mat[fill] <- sample(fill, 1:10, replace = TRUE)

可以使用以下方法进行离散化:

mat[mat > 0] <- 1

在我的工作站上非常快:

> system.time(mat[mat > 0] <- 1)
   user  system elapsed 
  1.680   0.166   1.875

还有一个简单的问题,如果我想对同一矩阵的每一列求和并将其放入向量中,该怎么办。也就是说,如果第一列中元素的总和为5,第二列为4,...那么最终我将得到一个SUM向量[5,4,..]。 - dave
colSums()将是我的首选。阅读 ?colSums. - Gavin Simpson
@user808562,如果问题已经得到解决(至少有两个答案看起来已经解决了问题),请接受其中一个答案。在每个答案左边的方框中打勾。@Andrie是第一个给出解决方案的人... - Gavin Simpson

2
如果您使用Matrix包,且矩阵为Mat,则可以将Mat@x作为向量进行运算。例如:ix_low <- (Mat@x < threshold),然后Mat@x[ix_low] = 0, Mat@x[!ix_low] = 1
关键是当您查看稀疏矩阵时,您的思考方式是错误的。典型的表示形式是(i,j,value)。
您只需要触摸值向量-不要迭代其他任何内容。

谢谢,这太棒了。我简直不敢相信我在R屏幕前浪费了这么多时间。原来这么简单 :) - dave
我已经在那里了。我在那里呆得太久了。 :) - Iterator

0
一种处理正式定义的稀疏矩阵(即在基础“Matrix”中生成的矩阵,使用大写字母M而不是旧基础“matrix”)的简单方法是使用“as”命令将矩阵强制转换为逻辑形式,然后再转换回数值或整数矩阵。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接