您正在寻找的是multisets 的排列。
library(RcppAlgos)
multiPerm <- permuteGeneral(1:4, freqs = rep(2,4))
head(multiPerm)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 1 2 2 3 3 4 4
[2,] 1 1 2 2 3 4 3 4
[3,] 1 1 2 2 3 4 4 3
[4,] 1 1 2 2 4 3 3 4
[5,] 1 1 2 2 4 3 4 3
[6,] 1 1 2 2 4 4 3 3
完整性检查:
library(combinat)
library(gtools)
OPTestOne <- unlist(unique(permn(c(1,1,2,2,3,3,4,4), paste0, collapse = "")))
all.equal(sort(apply(multiPerm, 1, paste, collapse="")), sort(OPTestOne))
[1] TRUE
OPTestTwo <- unique(permutations(8,8,c(1,1,2,2,3,3,4,4), set=FALSE))
all.equal(OPTestTwo, multiPerm)
[1] TRUE
以下是一些基准:
library(microbenchmark)
microbenchmark(OP_One = unique(permn(c(1,1,2,2,3,3,4,4), paste0, collapse = "")),
Algos = permuteGeneral(1:4, freqs = rep(2,4)),
OP_Two = unique(permutations(8,8,c(1,1,2,2,3,3,4,4), set=FALSE)),
times = 5, unit = "relative")
Unit: relative
expr min lq mean median uq max neval
OP_One 8435.40 5570.476 5877.457 5562.094 5378.490 5409.687 5
Algos 1.00 1.000 1.000 1.000 1.000 1.000 5
OP_Two 15335.55 10095.646 10700.802 9982.139 9539.425 10295.974 5
寻找多重集合的排列选择m也没有问题。
system.time(multiPermChoose11 <- permuteGeneral(1:4, m = 11, freqs = rep(4, 4)))
user system elapsed
0.154 0.023 0.178
head(multiPermChoose11)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
[1,] 1 1 1 1 2 2 2 2 3 3 3
[2,] 1 1 1 1 2 2 2 3 2 3 3
[3,] 1 1 1 1 2 2 2 3 3 2 3
[4,] 1 1 1 1 2 2 2 3 3 3 2
[5,] 1 1 1 1 2 2 3 2 2 3 3
[6,] 1 1 1 1 2 2 3 2 3 2 3
对于后一个示例,OP 对有多少排列 (525,525) 的猜测是不正确的。发现这是一个little more involved,而不是提供的一个班轮。
nrow(multiPermChoose11)
[1] 2310000
只是为了表明这是正确的:
length(unique(apply(multiPermChoose11, 1, paste, collapse ="")))
[1] 2310000
还有一个来自iterpc 的函数,用于计算多重集的排列数,称为np_multiset
iterpc::np_multiset(rep(4,4), 11)
[1] 2310000
有关 R 中此类问题的更多信息,我为该问题写了一个 thorough overview:@RandyLai 的 R: Permutations and combinations with/without replacement and for distinct/non-distinct items/multiset(arrangements 和 iterpc 的作者,两者都能够完成上述工作有效。)