rpermutation

Generate permutations of specific length with repetition in R?


I have a list of words and I need to generate all the permutations with repetition. The length of permutation must be specified. The words list is quite big(i.e. 30 words) so the function I needs to be efficient too.. Example:

wordsList = c("alice", "moon", "walks", "mars", "sings", "guitar", "bravo")

I need to generate all the permutations given that each permutation must have exactly 3 words. That would be ["alice", "moon", "walks"], ["alice", "walks", "moon"], ["moon", "alice", "walks"] etc


Solution

  • There are several packages that will produce exactly what you need. Let’s start with the classic gtools. Also, from the looks of the example provided by the OP, we are looking for permutations without repetition, not combinations with repetition.

    wordsList <- c("alice", "moon", "walks", "mars", "sings", "guitar", "bravo")
    
    library(gtools)
    attempt1 <- permutations(length(wordsList), 3, wordsList)
    head(attempt1)
    #>      [,1]    [,2]     [,3]    
    #> [1,] "alice" "bravo"  "guitar"
    #> [2,] "alice" "bravo"  "mars"  
    #> [3,] "alice" "bravo"  "moon"  
    #> [4,] "alice" "bravo"  "sings" 
    #> [5,] "alice" "bravo"  "walks" 
    #> [6,] "alice" "guitar" "bravo"
    

    Then there is arrangements:

    library(arrangements)
    #> 
    #> Attaching package: 'arrangements'
    #> The following objects are masked from 'package:gtools':
    #> 
    #>     combinations, permutations
    
    attempt2 <- permutations(wordsList, 3)
    head(attempt2)
    #>      [,1]    [,2]    [,3]    
    #> [1,] "alice" "moon"  "walks" 
    #> [2,] "alice" "moon"  "mars"  
    #> [3,] "alice" "moon"  "sings" 
    #> [4,] "alice" "moon"  "guitar"
    #> [5,] "alice" "moon"  "bravo" 
    #> [6,] "alice" "walks" "moon"
    

    And finally, RcppAlgos (I am the author):

    library(RcppAlgos)
    attempt3 <- permuteGeneral(wordsList, 3)
    

    They are all fairly efficient and produce similar outcomes (different orderings)

    identical(attempt1[do.call(order,as.data.frame(attempt1)),],
              attempt2[do.call(order,as.data.frame(attempt3)),])
    #> [1] TRUE
    
    identical(attempt2, attempt3)
    #> [1] TRUE
    

    If you really want permutations with repetition, each function provides an argument for carrying out that function. For gtools set repeats.allowed = TRUE, for arrangments set replace = TRUE, and finally for RcppAlgos set repetition = TRUE.

    Since the OP is working with a wordsList with many words and is looking for all permutations chosen 15 at a time, the aforementioned methods will fail. However, there are some alternatives from arrangements as well as RcppAlgos that may help.

    With arrangements you can use the method getnext and produce successive permutations. Generating them all will still take quite a long time.

    As with arrangements, RcppAlgos provides access to memory efficient iterators. They are quite flexible and very fast.

    it <- permuteIter(wordsList, 3)
    
    ## start iterating
    it@nextIter()
    #> [1] "alice" "moon"  "walks"
    
    ## draw n at a time
    it@nextNIter(n = 3)
    #>      [,1]    [,2]   [,3]    
    #> [1,] "alice" "moon" "mars"  
    #> [2,] "alice" "moon" "sings" 
    #> [3,] "alice" "moon" "guitar"
    
    ## get the last one
    it@back()
    #> [1] "bravo"  "guitar" "sings"
    
    ## iterate in reverse
    it@prevIter()
    #> [1] "bravo"  "guitar" "mars"