How to combine two tibbles in all possible variations?

Let's say I have two tibbles:

p1 <- tribble(
    ~participant, ~bodypart, ~col,
    "left",           "head",    1,
    "left",           "body",    2
)

p2 <- tribble(
    ~participant, ~bodypart, ~col,
    "right",         "head",    3,
    "right",         "body",    4
)

What I want to do is create a combined tibble that contains all combination of cols, so my result should look like this:

# A tibble: 4 x 6
  participant1 bodypart1  col1 participant2 bodypart2  col2
  <chr>        <chr>     <dbl> <chr>        <chr>     <dbl>
1 left         head          1 right        head          3
2 left         head          1 right        body          4
3 left         body          2 right        head          3
4 left         body          2 right        body          4

How can I do this?

We could use tidyr::expand() to generate all combinations of col1 and col2 and then join p1 and p2 to retrieve the remaining columns.

library(dplyr, warn.conflicts = FALSE)

p1 <- tribble(
  ~participant, ~bodypart, ~col,
  "left",           "head",    1,
  "left",           "body",    2
)

p2 <- tribble(
  ~participant, ~bodypart, ~col,
  "right",         "head",    3,
  "right",         "body",    4
)

p1 %>% 
  bind_cols(p2) %>% 
  tidyr::expand(col, col1) %>% 
  left_join(p1, by = "col") %>% 
  left_join(p2, by = c("col1" = "col")) %>% 
  select(participant1 = participant.x, bodypart1 = bodypart.x, col1 = col,
         participant2 = participant.y, bodypart2 = bodypart.y, col2 = col1)
#> # A tibble: 4 x 6
#>   participant1 bodypart1  col1 participant2 bodypart2  col2
#>   <chr>        <chr>     <dbl> <chr>        <chr>     <dbl>
#> 1 left         head          1 right        head          3
#> 2 left         head          1 right        body          4
#> 3 left         body          2 right        head          3
#> 4 left         body          2 right        body          4

Created on 2020-05-19 by the reprex package (v0.3.0)

Here is a solution using merge().

library(tibble)
p1 <- tribble(
  ~participant, ~bodypart, ~col,
  "left",           "head",    1,
  "left",           "body",    2
)

p2 <- tribble(
  ~participant, ~bodypart, ~col,
  "right",         "head",    3,
  "right",         "body",    4
)
merge(p1,p2, all =TRUE, by = NULL)
#>   participant.x bodypart.x col.x participant.y bodypart.y col.y
#> 1          left       head     1         right       head     3
#> 2          left       body     2         right       head     3
#> 3          left       head     1         right       body     4
#> 4          left       body     2         right       body     4

Created on 2020-05-19 by the reprex package (v0.3.0)

2 Likes

This is perfect, thank you!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.