Permute all unique enumerations of a vector in R

前端 未结 7 796
忘了有多久
忘了有多久 2020-11-29 06:21

I\'m trying to find a function that will permute all the unique permutations of a vector, while not counting juxtapositions within subsets of the same element type.

7条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-29 06:43

    EDIT: Here's a faster answer; again based on the ideas of Louisa Grey and Bryce Wagner, but with faster R code thanks to better use of matrix indexing. It's quite a bit faster than my original:

    > ffffd <- 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 
    

    And the code:

    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)
    }
    

    It doesn't return the same order, but after sorting, the results are identical.

    up1a <- up1[do.call(order, as.data.frame(up1)),]
    up2a <- up2[do.call(order, as.data.frame(up2)),]
    identical(up1a, up2a)
    

    For my first attempt, see the edit history.

提交回复
热议问题