0

Given the vector:

a <- c(1,2,3)

I'm trying to calculate all vectors containing combinations from the elements in a, which is:

list(
    a[c(1,2,3)],
    a[c(1,3,2)],
    a[c(2,1,3)],
    a[c(2,3,1)],
    a[c(3,1,2)],
    a[c(3,2,1)])

This can be reproduced with:

df <- expand.grid(rep(list(a), length(a)))
nunique <- apply(df, 1, function(x) length(unique(x)))
df <- df[nunique == ncol(df), ]
as.list(as.data.frame(t(df)))

I tried doing this with the expand.grid but this function gives permutations where elements can be repeated which results in extra large dataset and gives the error from below.

I have seen similar questions to this but fail to find a fast solution that doesn't produce error:

Error: cannot allocate vector of size 37.3 Gb

The error can be reproduced for:

a <- c(1,2,3,4,5,6,7,8,9,10)
Joseph Wood
  • 7,077
  • 2
  • 30
  • 65
adl
  • 1,390
  • 16
  • 36
  • With large datasets, the combinations will be too large. You may need to carry out the operation on a system with more memory – akrun Sep 19 '18 at 15:53
  • 2
    You seem to want permutations rather than combinations (all 6 of your output vectors correspond to just a single combination but form a listing of the 3! = 6 permutations). See [this question](https://stackoverflow.com/q/11095992/4996248) for some pointers. – John Coleman Sep 19 '18 at 16:01
  • 2
    The package [arrangements](https://cloud.r-project.org/web/packages/arrangements/index.html) contains both generators and iterators (so you don't have to hold them in memory all at once if you simply want to loop over them) of permutations. [Benchmarks](https://stackoverflow.com/a/47983855/4996248) suggest that it is much faster than some of the alternatives such as `combinat`. – John Coleman Sep 19 '18 at 16:18

1 Answers1

2

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
  • As @JohnColeman points out, there are much more efficient packages for this type of task. For example, the package `arrangements` return all of the permutations of `1:10` in about a tenth of a second. Try `system.time(arrangements::permutations(10, 10))`. – Joseph Wood Sep 19 '18 at 17:52