假设v=c(-1,-1,-1,0,0,0,1,1,1)
并且我想生成所有排列。有9!/(3!3!3!)=1680
目前,我使用以下行来获取该功能,但效率不高。
unique(replicate(100000, sample(v), simplify=FALSE))
这是一种可能的情况。我想概括一下。假设n
个对象由k
个不同的对象a1,a2,...,ak
组成,并且重复数字为n1,n2,...,nk (n1+n2+...+nk=n)
。然后n!/(n1!n2!...nk!)
我该如何有效地做到这一点?
答案 0 :(得分:2)
试试这个:
<script src="https://www.amcharts.com/lib/3/ammap.js"></script>
<script src="https://www.amcharts.com/lib/3/maps/js/worldLow.js"></script>
<script src="https://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>
答案 1 :(得分:2)
最简单的解决方案是使用iterpc
包
library(iterpc)
getall(iterpc(table(v), ordered = TRUE))
它比ds440的combinat::permn
方法快至少5000倍。
> system.time(unique(combinat::permn(v)))
user system elapsed
4.861 0.037 4.902
> system.time(getall(iterpc(table(v), ordered = TRUE)))
user system elapsed
0.001 0.000 0.001
比sirallen方法快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 :(得分: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)