我需要将矩阵非零元素的索引保存到文件中。这适用于小型矩阵,在a
中存储非零索引的行号,在b
中存储非零索引的列号:
X <- matrix(c(1,0,3,4,0,5), byrow=TRUE, nrow=2);
a <- row(X)[which(!X == 0)]
b <- col(X)[which(!X == 0)]
但是矩阵的大小很大,我需要找到一种将索引保存到txt文件的有效方法,这样我就有[1] b [1](新行)a [2] b [ 2]等等。有什么建议吗?
答案 0 :(得分:4)
包Matrix
对于极大的矩阵有很好的解决方案。 sparseMatrix
对象可以归纳为data.frame,其中i
和j
是您的索引,x
是值:
X <- matrix(c(1,0,3,4,0,5), byrow=TRUE, nrow=2);
a <- row(X)[which(!X == 0)]
b <- col(X)[which(!X == 0)]
library(Matrix)
Y <- Matrix(X, sparse = TRUE)
(res <- summary(Y))
2 x 3 sparse Matrix of class "dgCMatrix", with 4 entries
i j x
1 1 1 1
2 2 1 4
3 1 3 3
4 2 3 5
class(res)
[1] "sparseSummary" "data.frame"
然后,您可以通过子集来获取i
和j
:
res[, c("i", "j")]
i j
1 1 1
2 2 1
3 1 3
4 2 3
答案 1 :(得分:2)
您可以使用带参数which
的{{1}}抓取所有非零位置的行和列,并将结果写入arr.ind=TRUE
的文件中:
write.table
这会在指定文件中产生以空格分隔的元素对的输出:
write.table(which(X != 0, arr.ind=TRUE), "file.txt", row.names=F, col.names=F)
将1 1
2 1
1 3
2 3
与which
一起使用可以在输入矩阵中保存一些扫描,与您问题中发布的代码相比,所以在计算要输出的数据时应该更快一些。您可以通过更大矩阵(1000 x 1000,密度为1%)的基准来看到这一点:
arr.ind=TRUE
在这种情况下,我们看到计算非零行和列的速度提高了5倍。根据矩阵的密度和大小,输出操作(set.seed(144)
bigX <- matrix(sample(c(rep(0, 99), 1), 1000000, replace=T), nrow=1000)
OP <- function(X) cbind(row(X)[which(!X == 0)], col(X)[which(!X == 0)])
josilber <- function(X) which(X != 0, arr.ind=TRUE)
library(microbenchmark)
microbenchmark(OP(bigX), josilber(bigX))
# Unit: milliseconds
# expr min lq mean median uq max neval
# OP(bigX) 20.513535 23.014517 36.463423 25.354250 59.130520 65.50304 100
# josilber(bigX) 3.873165 4.281624 6.741824 5.250777 6.998415 45.02542 100
)可能会成为瓶颈,在这种情况下,这种方法可能没有太大的好处。