expand_grid with identical vectors

Viewed 79

Problem:

Is there a simple way to get all combinations of two (or more) identical vectors. But only show unique combinations.

Reproducible example:

library(tidyr)

x = 1:3

expand_grid(a = x, 
            b = x, 
            c = x)

# A tibble: 27 x 3
       a     b     c
   <int> <int> <int>
 1     1     1     1
 2     1     1     2
 3     1     1     3
 4     1     2     1
 5     1     2     2
 6     1     2     3
 7     1     3     1
 8     1     3     2
 9     1     3     3
10     2     1     1
# ... with 17 more rows

But, if row 1 2 1 exists, then I do not want to see 1 1 2 or 2 1 1. I.e. show only unique combinations of the three vectors (any order).

4 Answers
library(gtools)
x = 1:3
df <- as.data.frame(combinations(n=3,r=3,v=x,repeats.allowed=T))
df

output

  V1 V2 V3
1   1  1  1
2   1  1  2
3   1  1  3
4   1  2  2
5   1  2  3
6   1  3  3
7   2  2  2
8   2  2  3
9   2  3  3
10  3  3  3

You can just sort rowwise and remove duplicates. Continuing from your expand_grid(), then

df <- tidyr::expand_grid(a = x, 
            b = x, 
            c = x)

data.frame(unique(t(apply(df, 1, sort))))


   X1 X2 X3
1   1  1  1
2   1  1  2
3   1  1  3
4   1  2  2
5   1  2  3
6   1  3  3
7   2  2  2
8   2  2  3
9   2  3  3
10  3  3  3

Using comboGeneral from the RcppAlgos package, it's implemented in C++ and pretty fast.

x <- 1:3
RcppAlgos::comboGeneral(x, repetition=TRUE)
#       [,1] [,2] [,3]
#  [1,]    1    1    1
#  [2,]    1    1    2
#  [3,]    1    1    3
#  [4,]    1    2    2
#  [5,]    1    2    3
#  [6,]    1    3    3
#  [7,]    2    2    2
#  [8,]    2    2    3
#  [9,]    2    3    3
# [10,]    3    3    3

Note: If you're running Linux, you will need gmp installed, e.g. for Ubuntu do:

sudo apt install libgmp3-dev

base

x <- 1:3

df <- expand.grid(a = x, 
            b = x, 
            c = x)

df[!duplicated(apply(df, 1, function(x) paste(sort(x), collapse = ""))), ]
#>    a b c
#> 1  1 1 1
#> 2  2 1 1
#> 3  3 1 1
#> 5  2 2 1
#> 6  3 2 1
#> 9  3 3 1
#> 14 2 2 2
#> 15 3 2 2
#> 18 3 3 2
#> 27 3 3 3

Created on 2021-09-09 by the reprex package (v2.0.1)

Related