rcombinationspermutationmultisetr-faq

How to generate permutations or combinations of object in R?


How to generate sequences of r objects from n objects? I'm looking for a way to do either permutations or combinations, with/without replacement, with distinct and non-distinct items (aka multisets).

This is related to twelvefold way. The "distinct" solutions could be included in twelvefold way, while the "non-distinct" are not included.


Solution

  • EDIT: I have updated the answer to use a more efficient package arrangements

    Getting start of using arrangement

    arrangements contains some efficient generators and iterators for permutations and combinations. It has been demonstrated that arrangements outperforms most of the existing packages of similar kind. Some benchmarks could be found here.

    Here are the answers to the above questions

    # 1) combinations: without replacement: distinct items
    
    combinations(5, 2)
    
          [,1] [,2]
     [1,]    1    2
     [2,]    1    3
     [3,]    1    4
     [4,]    1    5
     [5,]    2    3
     [6,]    2    4
     [7,]    2    5
     [8,]    3    4
     [9,]    3    5
    [10,]    4    5
    
    
    # 2) combinations: with replacement: distinct items
    
    combinations(5, 2, replace=TRUE)
    
          [,1] [,2]
     [1,]    1    1
     [2,]    1    2
     [3,]    1    3
     [4,]    1    4
     [5,]    1    5
     [6,]    2    2
     [7,]    2    3
     [8,]    2    4
     [9,]    2    5
    [10,]    3    3
    [11,]    3    4
    [12,]    3    5
    [13,]    4    4
    [14,]    4    5
    [15,]    5    5
    
    
    
    # 3) combinations: without replacement: non distinct items
    
    combinations(x = c("a", "b", "c"), freq = c(2, 1, 1), k = 2)
    
         [,1] [,2]
    [1,] "a"  "a" 
    [2,] "a"  "b" 
    [3,] "a"  "c" 
    [4,] "b"  "c" 
    
    
    
    # 4) combinations: with replacement: non distinct items
    
    combinations(x = c("a", "b", "c"), k = 2, replace = TRUE)  # as `freq` does not matter
    
         [,1] [,2]
    [1,] "a"  "a" 
    [2,] "a"  "b" 
    [3,] "a"  "c" 
    [4,] "b"  "b" 
    [5,] "b"  "c" 
    [6,] "c"  "c" 
    
    # 5) permutations: without replacement: distinct items
    
    permutations(5, 2)
    
          [,1] [,2]
     [1,]    1    2
     [2,]    1    3
     [3,]    1    4
     [4,]    1    5
     [5,]    2    1
     [6,]    2    3
     [7,]    2    4
     [8,]    2    5
     [9,]    3    1
    [10,]    3    2
    [11,]    3    4
    [12,]    3    5
    [13,]    4    1
    [14,]    4    2
    [15,]    4    3
    [16,]    4    5
    [17,]    5    1
    [18,]    5    2
    [19,]    5    3
    [20,]    5    4
    
    
    
    # 6) permutations: with replacement: distinct items
    
    permutations(5, 2, replace = TRUE)
    
          [,1] [,2]
     [1,]    1    1
     [2,]    1    2
     [3,]    1    3
     [4,]    1    4
     [5,]    1    5
     [6,]    2    1
     [7,]    2    2
     [8,]    2    3
     [9,]    2    4
    [10,]    2    5
    [11,]    3    1
    [12,]    3    2
    [13,]    3    3
    [14,]    3    4
    [15,]    3    5
    [16,]    4    1
    [17,]    4    2
    [18,]    4    3
    [19,]    4    4
    [20,]    4    5
    [21,]    5    1
    [22,]    5    2
    [23,]    5    3
    [24,]    5    4
    [25,]    5    5
    
    
    # 7) permutations: without replacement: non distinct items
    
    permutations(x = c("a", "b", "c"), freq = c(2, 1, 1), k = 2)
    
         [,1] [,2]
    [1,] "a"  "a" 
    [2,] "a"  "b" 
    [3,] "a"  "c" 
    [4,] "b"  "a" 
    [5,] "b"  "c" 
    [6,] "c"  "a" 
    [7,] "c"  "b" 
    
    
    
    # 8) permutations: with replacement: non distinct items
    
    permutations(x = c("a", "b", "c"), k = 2, replace = TRUE)  # as `freq` doesn't matter
    
          [,1] [,2]
     [1,] "a"  "a" 
     [2,] "a"  "b" 
     [3,] "a"  "c" 
     [4,] "b"  "a" 
     [5,] "b"  "b" 
     [6,] "b"  "c" 
     [7,] "c"  "a" 
     [8,] "c"  "b" 
     [9,] "c"  "c" 
    

    Compare to other packages

    There are few advantages of using arrangements over the existing packages.

    1. Integral framework: you don't have to use different packages for different methods.

    2. It is very efficient. See https://randy3k.github.io/arrangements/articles/benchmark.html for some benchmarks.

    3. It is memory efficient, it is able to generate all 13! permutation of 1 to 13, existing packages will fail to do so because of the limitation of matrix size. The getnext() method of the iterators allow users to get the arrangements one by one.

    4. The generated arrangements are in dictionary order which may be desired for some users.