Search code examples
router-joincartesian-product

Is it possible to use outer() to generate a Cartesian product?


To get a Cartesian product in R, we can use

library(tidyr)
x <- 1:2
y <- 1:3
expand_grid(x, y)

with output:

# A tibble: 6 x 2
      x     y
  <int> <int>
1     1     1
2     1     2
3     1     3
4     2     1
5     2     2
6     2     3

But I would like to output to be matrix-like, as with:

outer(x, y, FUN = "+")

which gives the output:

     [,1] [,2] [,3]
[1,]    2    3    4
[2,]    3    4    5

Is there a FUN = for outer() that will produce the Cartesian product:

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

Solution

  • There is no FUN in expand_grid. An option is to use mutate to create a new column and then reshape back to 'wide' with pivot_wider

    library(dplyr)
    library(tidyr)
    expand_grid(x, y) %>% 
         mutate(out = x + y) %>% 
         pivot_wider(names_from = y, values_from = out) %>%
         select(-x) %>%
         as.matrix %>% 
         `dimnames<-`(., NULL)
    

    -output

          [,1] [,2] [,3]
    [1,]    2    3    4
    [2,]    3    4    5
    

    Regarding the second question, it seems that the OP wanted to store each element of the matrix as a list

    out1 <- outer(x, y, FUN = Vectorize(function(x, y) list(c(x, y))))
    

    -output

    out1
         [,1]      [,2]      [,3]     
    [1,] integer,2 integer,2 integer,2
    [2,] integer,2 integer,2 integer,2