簡體   English   中英

使用combn()和bigmemory包生成一個非常大的字符串組合矩陣

[英]Generating a very large matrix of string combinations using combn() and bigmemory package

我有一個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'

有沒有辦法將這兩個功能結合起來得到我需要的東西? 有沒有其他方法可以實現這一目標? 謝謝。

這是我用R編寫的函數,它目前在LSPM包中找到它的(未導出的)主頁。 你給它的項目總數n ,項目選擇的號碼r並且希望組合的索引i ; 它返回對應於組合i 1:n的值。

".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 ++,做循環/寫在那里,因為它是快了很多

您可以先找到所有雙向組合,然后將它們與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" 

在第一次近似時, 每個算法都以存儲速度換取速度。

您已嘗試預先分配完全枚舉的組合矩陣。 所以也許你應該嘗試不預先分配這個矩陣,但試試,比方說,

  1. 如果您認為需要這些組合,請在其他地方計算它們並將它們存儲在一個簡單的數據庫(或者,平面文件)中並查找它們 - 保存9 gb

  2. 利用開源,讀取代碼以combn()並將其修改為客戶端 - 服務器東西:給定索引號為N的調用,它將循環並返回第N個條目。 效率不高,但可能更容易實現

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM