Permute all unique enumerations of a vector in R

前端 未结 7 682
忘了有多久
忘了有多久 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条回答
  • 2020-11-29 06:52

    As this question is old and continues to attract many views, this post is solely meant to inform R users of the current state of the language with regards to performing the popular task outlined by the OP. As @RandyLai alludes to, there are packages developed with this task in mind. They are: arrangements and RcppAlgos*.

    Efficiency

    They are very efficient and quite easy to use for generating permutations of a multiset.

    dat <- c(1, 0, 3, 4, 1, 0, 0, 3, 0, 4)
    dim(RcppAlgos::permuteGeneral(sort(unique(dat)), freqs = table(dat)))
    [1] 18900    10
    
    microbenchmark(algos = RcppAlgos::permuteGeneral(sort(unique(dat)), freqs = table(dat)),
                   arngmnt = arrangements::permutations(sort(unique(dat)), freq = table(dat)),
                   curaccptd = uniqueperm2(dat), unit = "relative")
    Unit: relative
         expr       min        lq       mean    median        uq       max neval
        algos  1.000000  1.000000  1.0000000  1.000000  1.000000 1.0000000   100
      arngmnt  1.501262  1.093072  0.8783185  1.089927  1.133112 0.3238829   100
    curaccptd 19.847457 12.573657 10.2272080 11.705090 11.872955 3.9007364   100
    

    With RcppAlgos we can utilize parallel processing for even better efficiency on larger examples.

    hugeDat <- rep(dat, 2)[-(1:5)]
    RcppAlgos::permuteCount(sort(unique(hugeDat)), freqs = table(hugeDat))
    [1] 3603600
    
    microbenchmark(algospar = RcppAlgos::permuteGeneral(sort(unique(hugeDat)),
                                                        freqs = table(hugeDat), nThreads = 4),
                   arngmnt = arrangements::permutations(sort(unique(hugeDat)), freq = table(hugeDat)),
                   curaccptd = uniqueperm2(hugeDat), unit = "relative", times = 10)
    Unit: relative
         expr      min        lq      mean    median       uq      max neval
     algospar  1.00000  1.000000  1.000000  1.000000  1.00000  1.00000    10
      arngmnt  3.23193  3.109092  2.427836  2.598058  2.15965  1.79889    10
    curaccptd 49.46989 45.910901 34.533521 39.399481 28.87192 22.95247    10
    

    Lexicographical Order

    A nice benefit of these packages is that the output is in lexicographical order:

    head(RcppAlgos::permuteGeneral(sort(unique(dat)), freqs = table(dat)))
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    [1,]    0    0    0    0    1    1    3    3    4     4
    [2,]    0    0    0    0    1    1    3    4    3     4
    [3,]    0    0    0    0    1    1    3    4    4     3
    [4,]    0    0    0    0    1    1    4    3    3     4
    [5,]    0    0    0    0    1    1    4    3    4     3
    [6,]    0    0    0    0    1    1    4    4    3     3
    
    tail(RcppAlgos::permuteGeneral(sort(unique(dat)), freqs = table(dat)))
             [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    [18895,]    4    4    3    3    0    1    1    0    0     0
    [18896,]    4    4    3    3    1    0    0    0    0     1
    [18897,]    4    4    3    3    1    0    0    0    1     0
    [18898,]    4    4    3    3    1    0    0    1    0     0
    [18899,]    4    4    3    3    1    0    1    0    0     0
    [18900,]    4    4    3    3    1    1    0    0    0     0
    
    identical(RcppAlgos::permuteGeneral(sort(unique(dat)), freqs = table(dat)),
          arrangements::permutations(sort(unique(dat)), freq = table(dat)))
    [1] TRUE
    

    Iterators

    Additionally, both packages offer iterators that allow for memory efficient generation of permutation, one by one:

    algosIter <- RcppAlgos::permuteIter(sort(unique(dat)), freqs = table(dat))
    
    algosIter$nextIter()
    [1] 0 0 0 0 1 1 3 3 4 4
    
    algosIter$nextNIter(5)
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    [1,]    0    0    0    0    1    1    3    4    3     4
    [2,]    0    0    0    0    1    1    3    4    4     3
    [3,]    0    0    0    0    1    1    4    3    3     4
    [4,]    0    0    0    0    1    1    4    3    4     3
    [5,]    0    0    0    0    1    1    4    4    3     3
    
    ## last permutation
    algosIter$back()
    [1] 4 4 3 3 1 1 0 0 0 0
    
    ## use reverse iterator methods
    algosIter$prevNIter(5)
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    [1,]    4    4    3    3    1    0    1    0    0     0
    [2,]    4    4    3    3    1    0    0    1    0     0
    [3,]    4    4    3    3    1    0    0    0    1     0
    [4,]    4    4    3    3    1    0    0    0    0     1
    [5,]    4    4    3    3    0    1    1    0    0     0
    

    * I am the author of RcppAlgos

    0 讨论(0)
提交回复
热议问题