How to Generate Permutations or Combinations of Object in R

How to generate permutations or combinations of object in R?

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.

Permutations of list elements in R

You will need to use one of the packages that are able to generate permutations of length n chosen m at a time (See this How to generate permutations or combinations of object in R? for more information). You can then loop over the rows and subset the orginal list:

library(gtools)

apply(permutations(length(my_list), 2), 1, function(x) {
my_list[x]
})

[[1]]
[[1]]$A
[1] "A"

[[1]]$B
[1] "B" "B"


[[2]]
[[2]]$A
[1] "A"

[[2]]$C
[1] "C" "C" "C"


[[3]]
[[3]]$B
[1] "B" "B"

[[3]]$A
[1] "A"


[[4]]
[[4]]$B
[1] "B" "B"

[[4]]$C
[1] "C" "C" "C"


[[5]]
[[5]]$C
[1] "C" "C" "C"

[[5]]$A
[1] "A"


[[6]]
[[6]]$C
[1] "C" "C" "C"

[[6]]$B
[1] "B" "B"

Generating all distinct permutations of a list in R

combinat::permn will do that work:

> library(combinat)
> permn(letters[1:3])
[[1]]
[1] "a" "b" "c"

[[2]]
[1] "a" "c" "b"

[[3]]
[1] "c" "a" "b"

[[4]]
[1] "c" "b" "a"

[[5]]
[1] "b" "c" "a"

[[6]]
[1] "b" "a" "c"

Note that calculation is huge if the element is large.

How to get a set of all Combination in R with given conditions?

Thanks @ekoam

lynx <- c(1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,4,4,4,5,5,6,7,8,9)

comb <- combinations(freq = table(lynx), k = 5, x = unique(lynx))

comb

library: arrangements

Unique Sets Permutations R

conbn would give you what you need:

 #combn gives you the combinations, t is only used to transpose the matrix
t(combn(x, 2))
# [,1] [,2]
#[1,] "A" "B"
#[2,] "A" "C"
#[3,] "A" "D"
#[4,] "B" "C"
#[5,] "B" "D"
#[6,] "C" "D"

R: how to obtain unique pairwise combinations of 2 vectors

We can use combn

f1 <- function(x) setNames(as.data.frame(t(combn(x, 2))), c("x", "y"))
f1(1:3)
# x y
#1 1 2
#2 1 3
#3 2 3

f1(1:4)
# x y
#1 1 2
#2 1 3
#3 1 4
#4 2 3
#5 2 4
#6 3 4

r - combinations from elements in vector

You seem to want permutations, not combinations. Try the function permn() from the package combinat:

# Your first example:
combinat::permn(c(1, 2, 3))
#> [[1]]
#> [1] 1 2 3
#>
#> [[2]]
#> [1] 1 3 2
#>
#> [[3]]
#> [1] 3 1 2
#>
#> [[4]]
#> [1] 3 2 1
#>
#> [[5]]
#> [1] 2 3 1
#>
#> [[6]]
#> [1] 2 1 3

# Your second example
res <- combinat::permn(c(1,2,3,4,5,6,7,8,9,10))

It does take a while, though. And of course the object itself is going to be large:

system.time(res <- combinat::permn(c(1,2,3,4,5,6,7,8,9,10)))
#> user system elapsed
#> 14.661 0.448 15.346
pryr::object_size(res)
#> 639 MB


Related Topics



Leave a reply



Submit