我试图找到一个函数,它将排列一个向量的所有唯一排列,而不计算同一元素类型的子集内的并置。例如:
dat <- c(1,0,3,4,1,0,0,3,0,4)
有
factorial(10)
> 3628800
可能的置换,但仅
10!/(2!*2!*4!*2!)
factorial(10)/(factorial(2)*factorial(2)*factorial(2)*factorial(4))
> 18900
忽略相同元素类型的子集内的并置时的唯一置换。
我可以通过使用包中的
unique()
和permn()
函数来获得这个结果。unique( permn(dat) )
但这在计算上非常昂贵,因为它涉及枚举
combinat
,这可能是比我需要的排列数量级更多的排列。有没有办法在不首先计算的情况下做到这一点? 最佳答案
编辑:这里是一个更快的答案;再次基于Louisa Grey和Bryce Wagner的想法,但更快的R代码感谢更好地使用矩阵索引。比我原来的要快一点:
> ddd <- c(1,0,3,4,1,0,0,3,0,4)
> system.time(up1 <- uniqueperm(d))
user system elapsed
0.183 0.000 0.186
> system.time(up2 <- uniqueperm2(d))
user system elapsed
0.037 0.000 0.038
以及代码:
uniqueperm2 <- function(d) {
dat <- factor(d)
N <- length(dat)
n <- tabulate(dat)
ng <- length(n)
if(ng==1) return(d)
a <- N-c(0,cumsum(n))[-(ng+1)]
foo <- lapply(1:ng, function(i) matrix(combn(a[i],n[i]),nrow=n[i]))
out <- matrix(NA, nrow=N, ncol=prod(sapply(foo, ncol)))
xxx <- c(0,cumsum(sapply(foo, nrow)))
xxx <- cbind(xxx[-length(xxx)]+1, xxx[-1])
miss <- matrix(1:N,ncol=1)
for(i in seq_len(length(foo)-1)) {
l1 <- foo[[i]]
nn <- ncol(miss)
miss <- matrix(rep(miss, ncol(l1)), nrow=nrow(miss))
k <- (rep(0:(ncol(miss)-1), each=nrow(l1)))*nrow(miss) +
l1[,rep(1:ncol(l1), each=nn)]
out[xxx[i,1]:xxx[i,2],] <- matrix(miss[k], ncol=ncol(miss))
miss <- matrix(miss[-k], ncol=ncol(miss))
}
k <- length(foo)
out[xxx[k,1]:xxx[k,2],] <- miss
out <- out[rank(as.numeric(dat), ties="first"),]
foo <- cbind(as.vector(out), as.vector(col(out)))
out[foo] <- d
t(out)
}
它不返回相同的顺序,但排序后,结果是相同的。
up1a <- up1[do.call(order, as.data.frame(up1)),]
up2a <- up2[do.call(order, as.data.frame(up2)),]
identical(up1a, up2a)
对于我的第一次尝试,请参见编辑历史记录。
关于algorithm - 在R中置换向量的所有唯一枚举,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5671149/