sbac
sbac

Reputation: 2081

How to create combinations of values of one variable by group using tidyverse in R

I am using the combn function in R to get all the combinations of the values of variable y taking each time 2 values, grouping by the values of x. My expected final result is the tibble c.

But when I try to do it in tidyverse something is (very) wrong.

library(tidyverse)

df <- tibble(x = c(1, 1, 1, 2, 2, 2, 2),
             y = c(8, 9, 7, 3, 5, 2, 1))


# This is what I want
a <- combn(df$y[df$x == 1], 2)
a <- rbind(a, rep(1, ncol(a)))


b <- combn(df$y[df$x == 2], 2)
b <- rbind(b, rep(2, ncol(b)))

c <- cbind(a, b)
c <- tibble(c)
c <- t(c)


# but using tidyverse it does not work
df %>% group_by(x) %>% mutate(z = combn(y, 2))
#> Error: Problem with `mutate()` input `z`.
#> x Input `z` can't be recycled to size 3.
#> i Input `z` is `combn(y, 2)`.
#> i Input `z` must be size 3 or 1, not 2.
#> i The error occurred in group 1: x = 1.
Created on 2020-11-18 by the reprex package (v0.3.0)

Upvotes: 4

Views: 474

Answers (3)

akrun
akrun

Reputation: 887098

An option with summarise and unnest

library(dplyr)
library(tidyr)
df %>% 
    group_by(x) %>% 
    summarise(y = list(as.data.frame(t(combn(y, 2)))), .groups = 'drop') %>% 
    unnest(c(y))
# A tibble: 9 x 3
#      x    V1    V2
#  <dbl> <dbl> <dbl>
#1     1     8     9
#2     1     8     7
#3     1     9     7
#4     2     3     5
#5     2     3     2
#6     2     3     1
#7     2     5     2
#8     2     5     1
#9     2     2     1

Upvotes: 1

ekoam
ekoam

Reputation: 8844

If you have dplyr v1.0.2, you can do this

df %>% group_by(x) %>% group_modify(~as_tibble(t(combn(.$y, 2L))))

Output

# A tibble: 9 x 3
# Groups:   x [2]
      x    V1    V2
  <dbl> <dbl> <dbl>
1     1     8     9
2     1     8     7
3     1     9     7
4     2     3     5
5     2     3     2
6     2     3     1
7     2     5     2
8     2     5     1
9     2     2     1

Upvotes: 2

BENY
BENY

Reputation: 323226

Try with combn

out = df %>% group_by(x) %>% do(data.frame(t(combn(.$y, 2))))
# A tibble: 9 x 3
# Groups:   x [2]
      x    X1    X2
  <dbl> <dbl> <dbl>
1     1     8     9
2     1     8     7
3     1     9     7
4     2     3     5
5     2     3     2
6     2     3     1
7     2     5     2
8     2     5     1
9     2     2     1

Upvotes: 2

Related Questions