combn()とbigmemoryパッケージを使用して、文字列の組み合わせの非常に大きなマトリックスを生成する
-
12-10-2019 - |
質問
1,344個のユニークな文字列のベクトルXがあります。順序に関係なく、3つの値のすべての可能なグループを提供するマトリックスを生成し、それをCSVにエクスポートしたいと思います。
M1.largeインスタンスW 64bit Ubuntuで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つの機能を組み合わせて必要なものを取得する方法はありますか?これを達成する他の方法はありますか?ありがとう。
解決
最初にすべての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()
ループの前に、その後(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"
他のヒント
これが私が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 ++に移植して、そこでループ /ライティングを行うことができます。 多くの もっと早く。
最初の近似で、 毎日 アルゴリズムはストレージを速度で取引します。
完全に列挙されたコンビネーションマトリックスを事前に表現しようとする境界にぶつかりました。したがって、このマトリックスを事前に表現しないでください。
組み合わせが必要だと思われる場合は、他の場所に計算して、簡単なDB(または、フラットファイル)に保存して調べてください-9 GB保存
オープンソースを利用して、コードを読んでください
combn()
そしてそれをaに変更します クライアントサーバー Thingy:インデックス番号の呼び出しが与えられました n, 、ループして戻ります nth エントリ。効率的ではありませんが、おそらくより簡単です 実行可能.