我有一个1,344个唯一字符串的向量x。我想生成一个矩阵,它给我所有可能的三个值组,无论顺序如何,并将其导出到csv。
我在m1.large实例w 64bit Ubuntu上运行EC on EC2。使用combn(x,3)时出现内存不足错误:
Error: cannot allocate vector of size 9.0 Gb
得到的矩阵的大小是C1344,3 = 403,716,544行和三列 - 这是combn()函数结果的转置。
我想过使用bigmemory包创建一个文件支持的big.matrix,然后我可以分配combn()函数的结果。我可以创建一个预分配的大矩阵:
library(bigmemory)
x <- as.character(1:1344)
combos <- 403716544
test <- filebacked.big.matrix(nrow = combos, ncol = 3,
init = 0, backingfile = "test.matrix")
但是当我尝试分配值test <- combn(x, 3)
时,我仍然会得到相同的结果:Error: cannot allocate vector of size 9.0 Gb
我甚至尝试强制combn(x,3)
的结果,但我认为因为combn()函数返回错误,big.matrix函数也不起作用。
test <- as.big.matrix(matrix(combn(x, 3)), backingfile = "abc")
Error: cannot allocate vector of size 9.0 Gb
Error in as.big.matrix(matrix(combn(x, 3)), backingfile = "abc") :
error in evaluating the argument 'x' in selecting a method for function 'as.big.matrix'
有没有办法将这两个功能组合在一起以获得我需要的东西?有没有其他方法可以实现这一目标?感谢。
答案 0 :(得分:5)
这是我用R编写的函数,它目前在LSPM包中找到它的(未导出的)主页。您可以为其指定项目总数n
,要选择的项目数r
以及所需组合的索引i
;它会返回与1:n
组合相对应的i
中的值。
".combinadic" <- function(n, r, i) {
# http://msdn.microsoft.com/en-us/library/aa289166(VS.71).aspx
# http://en.wikipedia.org/wiki/Combinadic
if(i < 1 | i > choose(n,r)) stop("'i' must be 0 < i <= n!/(n-r)!")
largestV <- function(n, r, i) {
#v <- n-1
v <- n # Adjusted for one-based indexing
#while(choose(v,r) > i) v <- v-1
while(choose(v,r) >= i) v <- v-1 # Adjusted for one-based indexing
return(v)
}
res <- rep(NA,r)
for(j in 1:r) {
res[j] <- largestV(n,r,i)
i <- i-choose(res[j],r)
n <- res[j]
r <- r-1
}
res <- res + 1
return(res)
}
它允许您根据词典索引的值生成每个组合:
> .combinadic(1344, 3, 1)
[1] 3 2 1
> .combinadic(1344, 3, 2)
[1] 4 2 1
> .combinadic(1344, 3, 403716544)
[1] 1344 1343 1342
所以你只需要遍历1:403716544并将结果追加到文件中。这可能需要一段时间,但至少是可行的(参见Dirk的回答)。你也可能需要在几个循环中完成它,因为向量1:403716544
不适合我机器的内存。
或者您可以将R代码移植到C / C ++并在那里进行循环/写入,因为它会很多更快。
答案 1 :(得分:3)
您可以先找到所有双向组合,然后将它们与3d值组合,同时每次都保存它们。这会占用更少的内存:
combn.mod <- function(x,fname){
tmp <- combn(x,2,simplify=F)
n <- length(x)
for ( i in x[-c(n,n-1)]){
# Drop all combinations that contain value i
id <- which(!unlist(lapply(tmp,function(t) i %in% t)))
tmp <- tmp[id]
# add i to all other combinations and write to file
out <- do.call(rbind,lapply(tmp,c,i))
write(t(out),file=fname,ncolumns=3,append=T,sep=",")
}
}
combn.mod(x,"F:/Tmp/Test.txt")
这不像约书亚的回答那么笼统,它特别针对你的情况。对于这个特殊情况,我想它更快 - 但是我没有进行比较。当应用于x时,功能在我的计算机上运行时使用超过50 Mb(粗略估计)。
修改
旁注:如果这是出于模拟目的,我发现很难相信任何科学应用需要4亿多次模拟运行。你可能会在这里问错了问题的正确答案......
概念证明:
我将写行改为tt[[i]]<-out
,在循环前添加tt <- list()
并在其后返回(tt)。然后:
> do.call(rbind,combn.mod(letters[1:5]))
[,1] [,2] [,3]
[1,] "b" "c" "a"
[2,] "b" "d" "a"
[3,] "b" "e" "a"
[4,] "c" "d" "a"
[5,] "c" "e" "a"
[6,] "d" "e" "a"
[7,] "c" "d" "b"
[8,] "c" "e" "b"
[9,] "d" "e" "b"
[10,] "d" "e" "c"
答案 2 :(得分:1)
在第一次近似时,每个算法都会以存储速度换取速度。
您已尝试预先分配完全枚举的组合矩阵。所以也许你应该尝试不预先分配这个矩阵,但试试,比方说,
如果您认为需要这些组合,请在其他地方计算它们并将它们存储在一个简单的数据库(或者,平面文件)中并查找它们 - 保存9 GB
利用开源,将代码读取到combn()
并将其修改为客户端 - 服务器东西:给定索引号为 N的调用,它将循环并返回第N 条目。效率不高,但可能更容易可行。