2016-04-27 7 views
1

変数の合計が100になるような 'n'変数のすべての可能な組み合わせを生成する必要があります。変数の範囲は0から100まであり、1のステップを変えることができます。 = 10の場合、結果のデータフレームにはすべての可能な組み合わせが含まれます。しかし、私は、ユーザーが開始時に引数としてnを渡す柔軟性を持つように、 'n'動的を作る可能性を探しています。 すべてのヘルプは高く評価されます。..ダイナミックネストされたfor-loopsを生成するためにRで再帰関数を書き込むにはどうすればよいですか?

row <- list() 
z = 1 
for (a in seq(from = 0, to = 100, by = 1)) { 
    for (b in seq(from = 0, to = 100, by = 1)) { 
    for (c in seq(from = 0, to = 100, by = 1)) { 
     for (d in seq(from = 0, to = 100, by = 1)) { 
     for (e in seq(from = 0, to = 100, by = 1)) { 
      for (f in seq(from = 0, to = 100, by = 1)) { 
      for (g in seq(from = 0, to = 100, by = 1)) { 
       for (h in seq(from = 0, to = 100, by = 1)) { 
       for (i in seq(from = 0, to = 100, by = 1)) { 
        for (j in seq(from = 0, to = 100, by = 1)) { 
        if (a + b + c + d + e + f + g + h + i + j == 100) { 
         row[[z]] <- (c(a,b,c,d,e,f,g,h,i,j)) 
         z = z + 1 
        }  
        } 
       } 
       } 
      } 
      } 
     }   
     }   
    } 
    } 
} 

finaldata <- as.data.frame(do.call(rbind, row)) 
+0

これは数論の問題です。それは、100という数のパーティション(ゼロが許されます)と呼ばれます。 9つのパーツを持つパーティションから10つのパーツでパーティションを再帰する必要があります(そして、8つのパーツから7つのパーツまで...)! – jogo

+0

例:10番目の部分は0,1、...、100の値を持つことができます。したがって、0から100までの部分の100を9 + 100の区画と1+ "99 in 9 parts"の部分と... – jogo

+0

あなたがこの問題を解決できたとしても、結果が気に入らないでしょう。 Rのforループのパフォーマンスはひどいです。この多くのネストされたループは、Rの闘争につながります。 – niczky12

答えて

0
parti <- function(n, k) { 
    if (n<0) { message("error: n<0"); return(NA) } 
    if (k==1) return(matrix(n,1,1)) 
    M <- cbind(parti(n, k-1), 0) 
    if (n>0) for (i in 1:n) M <- rbind(M, cbind(parti(n-i, k-1), i)) 
    M 
} 

parti(5, 3) 

結果:あなたの状況については

> parti(5, 3) 
     i 
[1,] 5 0 0 
[2,] 4 1 0 
[3,] 3 2 0 
[4,] 2 3 0 
[5,] 1 4 0 
[6,] 0 5 0 
[7,] 4 0 1 
[8,] 3 1 1 
[9,] 2 2 1 
[10,] 1 3 1 
[11,] 0 4 1 
[12,] 3 0 2 
[13,] 2 1 2 
[14,] 1 2 2 
[15,] 0 3 2 
[16,] 2 0 3 
[17,] 1 1 3 
[18,] 0 2 3 
[19,] 1 0 4 
[20,] 0 1 4 
[21,] 0 0 5 

(N = 100、K = 10)、多くのパーティションがあるので、あなたはメモリと時間とのトラブルを持っています!

1
ptn <- function(n,k) if (k<=1L) list(n) else do.call(c,lapply(seq_len(n+1L)-1L,function(x) lapply(ptn(x,k-1L),c,n-x))); 

デモ:

ptn(1,1); 
## [[1]] 
## [1] 1 
## 

ptn(2,1); 
## [[1]] 
## [1] 2 
## 

ptn(1,2); 
## [[1]] 
## [1] 0 1 
## 
## [[2]] 
## [1] 1 0 
## 

ptn(2,2); 
## [[1]] 
## [1] 0 2 
## 
## [[2]] 
## [1] 1 1 
## 
## [[3]] 
## [1] 2 0 
## 

ptn(3,2); 
## [[1]] 
## [1] 0 3 
## 
## [[2]] 
## [1] 1 2 
## 
## [[3]] 
## [1] 2 1 
## 
## [[4]] 
## [1] 3 0 
## 

ptn(3,3); 
## [[1]] 
## [1] 0 0 3 
## 
## [[2]] 
## [1] 0 1 2 
## 
## [[3]] 
## [1] 1 0 2 
## 
## [[4]] 
## [1] 0 2 1 
## 
## [[5]] 
## [1] 1 1 1 
## 
## [[6]] 
## [1] 2 0 1 
## 
## [[7]] 
## [1] 0 3 0 
## 
## [[8]] 
## [1] 1 2 0 
## 
## [[9]] 
## [1] 2 1 0 
## 
## [[10]] 
## [1] 3 0 0 
## 

あなたがしたいパーティションのセットを生成することは非現実的である、すなわち10から100にしても、5〜100がそれを推進して作る作る:

system.time({ x <- ptn(100,5); }); 
## user system elapsed 
## 32.594 0.141 32.790 
length(x); 
## [1] 4598126 
system.time({ print(unique(sapply(x,sum))); }); 
## [1] 100 
## user system elapsed 
## 6.938 0.063 7.004 
length(unique(x)); 
## [1] 4598126 

ここでは、パーティションセットのサイズを再帰的に計算する関数を作成しましたが、実際にそのセットを生成するためのCPUまたはメモリコストは発生しません。注:キャッシュは必須で、そうでないとCPUヒットは完全生成アルゴリズムに似ています。

ptnSize <- function(n,k,cache=new.env()) if (k<=1L) 1 else { key <- paste0(n,'/',k); if (is.null(cache[[key]])) cache[[key]] <- do.call(sum,lapply(seq_len(n+1L)-1L,function(x) ptnSize(x,k-1L,cache))); cache[[key]]; }; 

デモ:

ptnSize(1,1); 
## [1] 1 
ptnSize(2,1); 
## [1] 1 
ptnSize(1,2); 
## [1] 2 
ptnSize(2,2); 
## [1] 3 
ptnSize(3,2); 
## [1] 4 
ptnSize(3,3); 
## [1] 10 
ptnSize(100,5); 
## [1] 4598126 
ptnSize(100,10); 
## [1] 4.263422e+12 

私たちが見ることができるように、ご希望のパーティションのセットはかなり大きいです。私はそれが記憶するために何百テラバイトのメモリを必要とすると推定する。

+0

ありがとう、私が必要とするようにtonitが動作します..私はptn(100,10)がherculeanであることに気付きました、おそらく私は2または4のステップでパーティションを増やすことができます。 – sg7544

関連する問題