我有一个大的方形矩阵,包含每行或每列之间的相关性:
mat <- matrix(rnorm(5000 * 5000), nrow = 5000, dimnames = list(
paste0("ID", seq_len(5000)), paste0("ID", seq_len(5000))))
我想从这个矩阵中提取前100,000个唯一对(即ID1-ID2与ID2-ID1相同),然后将它们转换为数据帧。目前,我正在使用此代码:
corDat <- reshape2::melt(mat, varnames = c("id.A", "id.B"),
value.name = "value", na.rm = T)
corDat <- corDat[as.character(corDat$id.A) < as.character(corDat$id.B),]
corDat <- corDat[order(-corDat$value),]
top_n <- 100000
corDat <- corDat[seq_len(top_n),]
结果:
head(corDat)
id.A id.B value
19316931 ID1931 ID3864 5.658092
14312231 ID2231 ID2863 5.416562
3225529 ID529 ID646 5.357433
3492653 ID2653 ID699 5.297154
17046659 ID1659 ID3410 5.105343
3323364 ID3364 ID665 4.987266
...
然而,由于矩阵很大,上面的前两个操作(melt
矩阵并删除重复对)需要很长时间,通常超过5分钟。我需要将这个操作应用于几百个可变大小的矩形矩阵(通常大于5000x5000)。
我确信必须有更快的方法来提取这些信息,因为我实际上并不需要融合整个矩阵 - 只是与前100,000个值相关联的行和列名称。如何更有效地完成这项工作?
答案 0 :(得分:1)
这是使用索引的基本R版本:
up <- upper.tri(mat)
inds <- which( up , arr.ind = TRUE )
out <- data.frame( id.A = rownames(mat)[ inds[,1] ] , id.B = rownames(mat)[ inds[,2] ] , value = mat[up] )
#order and select the top ten:
out[order(-out$value),][1:10,]
在我的机器上,这比melt
快3.5倍。
我假设您想要矩阵的上三角部分。
请注意,由于多位数字符串比较的工作方式(例如as.character(corDat$id.A) < as.character(corDat$id.B)
评估为"ID10" < "ID7"
),因此TRUE
语句不会选择上三角形部分。