7

1,344個の一意の文字列のベクトルxがあります。順序に関係なく、3つの値のすべての可能なグループを提供するマトリックスを生成し、それをcsvにエクスポートしたいと思います。

64ビットUbuntuを使用したm1.largeインスタンスのEC2でRを実行しています。combn(x、3)を使用すると、メモリ不足エラーが発生します。

Error: cannot allocate vector of size 9.0 Gb

結果の行列のサイズはC1344,3=403,716,544行と3列です。これは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'

これらの2つの機能を組み合わせて、必要なものを取得する方法はありますか?これを達成する他の方法はありますか?ありがとう。

4

3 に答える 3

5

これが私がRで書いた関数で、現在LSPMパッケージにその(エクスポートされていない)ホームがあります。アイテムの総数n、選択するアイテムの数r、および必要な組み合わせのインデックスを指定しますi1: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 ++に移植して、そこでループ/書き込みを行うこともできます。これは、はるかに高速になるためです。

于 2010-12-20T22:10:28.823 に答える
3

最初にすべての2方向の組み合わせを見つけ、次にそれらを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()し、ループの後にreturn(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" 
于 2010-12-20T23:03:37.040 に答える
1

最初の概算では、すべてのアルゴリズムはストレージと速度のトレードオフを行います。

完全に列挙された組み合わせ行列を事前に割り当てようとして、境界に達しました。したがって、このマトリックスを事前に割り当てるのではなく、たとえば、

  1. 組み合わせが必要だと思われる場合は、それらを別の場所で計算し、単純なdb(または、一体、フラットファイル)に保存して検索します-9GB保存済み

  2. オープンソースを利用し、コードを読み取ってクライアントサーバーcombn()に変更します。インデックス番号Nの呼び出しが与えられると、ループしてN番目のエントリが返されます。効率的ではありませんが、おそらくより簡単に実行可能です。

于 2010-12-20T21:44:22.380 に答える