2016-11-30 4 views
1

v=c(-1,-1,-1,0,0,0,1,1,1)と仮定し、すべての順列を生成したいとします。 9!/(3!3!3!)=1680不完全な別個のオブジェクトのすべての可能な順列を生成するR

現在、私はそれを得るために次の行を使用していますが、あまり効率的ではありません。

unique(replicate(100000, sample(v), simplify=FALSE)) 

これは1つの可能性のあるケースです。私はこれを一般化したい。 nのオブジェクトがk個の異なるオブジェクトa1,a2,...,akと、繰り返し番号n1,n2,...,nk (n1+n2+...+nk=n)のものであるとします。次にn!/(n1!n2!...nk!)

これを効率的に行うにはどうすればよいですか?

答えて

2

最も簡単な解決策はiterpcパッケージ

library(iterpc) 
getall(iterpc(table(v), ordered = TRUE)) 

それはds440のcombinat::permnアプローチよりも少なくとも5000倍高速であるを使用することです。サイレントアプローチよりも10倍高速である。

> microbenchmark(getall(iterpc(table(v), ordered = TRUE)), sirallen()) 
Unit: microseconds 
            expr  min  lq  mean median 
getall(iterpc(table(v), ordered = TRUE)) 583.512 605.699 804.0107 748.9305 
           sirallen() 5784.122 7571.282 8777.4111 8256.1035 
2

このお試しください:

u = list(unique(v)) 
Pv = expand.grid(rep(u,9)) 
Pv = Pv[rowSums(Pv==-1)==3 & rowSums(Pv==0)==3,] 
1

一つのアプローチは、順列フィルタリング、すべての可能性を生成する機能を使用することです。すべての可能性を保証する必要がある場合、これはあなたの質問のサンプルメソッドよりも利点がありますが、長いベクトルがある場合は 'クラッシュする'ことがあります。

v=c(-1,-1,-1,0,0,0,1,1,1) 
unique(combinat::permn(v)) 

この方法は、@ sirallenのアプローチよりもはるかに簡単です。そのアプローチの一般化は以下のようになります。

u <- unique(v) 
Pv <- expand.grid(rep(list(u),length(v))) 
for(i in seq_along(u)) { 
Pv <- Pv[rowSums(Pv==u[i])==sum(u[i]==v),] 
} 
dim(Pv) 
関連する問題