kmace
kmace

Reputation: 2044

Expanding a data.frame based on (group) values from the data.frame

Lets say I have the following data frame:

tibble(user = c('A', 'B'), first = c(1,4), last = c(6, 9))
# A tibble: 2 x 3
  user  first  last
  <chr> <dbl> <dbl>
1 A         1     6
2 B         4     9

And want to create a tibble that looks like:

bind_rows(tibble(user = 'A', weeks = 1:6), 
          tibble(user = 'B', weeks = 4:9))
# A tibble: 12 x 2
   user  weeks
   <chr> <int>
 1 A         1
 2 A         2
 3 A         3
 4 A         4
 5 A         5
 6 A         6
 7 B         4
 8 B         5
 9 B         6
10 B         7
11 B         8
12 B         9

How could I go about doing this? I have tried:

tibble(user = c('A', 'B'), first = c(1,4), last = c(6, 9)) %>% 
group_by(user) %>% 
mutate(weeks = first:last)

I wonder if I should try a combination of complete map or nest?

Upvotes: 3

Views: 71

Answers (2)

akrun
akrun

Reputation: 887128

One option is unnest after creating a sequence

library(dplyr)
library(purrr)
df1 %>% 
  transmute(user, weeks = map2(first, last, `:`)) %>%
  unnest(weeks)
# A tibble: 12 x 2
#   user  weeks
#   <chr> <int>
# 1 A         1
# 2 A         2
# 3 A         3
# 4 A         4
# 5 A         5
# 6 A         6
# 7 B         4
# 8 B         5
# 9 B         6
#10 B         7
#11 B         8
#12 B         9

Or another option is rowwise

df1 %>% 
  rowwise %>%
  transmute(user, weeks = list(first:last)) %>% 
  unnest(weeks)

Or without any packages

stack(setNames(Map(`:`, df1$first, df1$last), df1$user))

Or otherwise written as

stack(setNames(do.call(Map, c(f = `:`, df1[-1])), df1$user))

data

df1 <- tibble(user = c('A', 'B'), first = c(1,4), last = c(6, 9))

Upvotes: 3

tmfmnk
tmfmnk

Reputation: 39858

One option involving dplyr and tidyr could be:

df %>%
 uncount(last - first + 1) %>%
 group_by(user) %>%
 transmute(weeks = first + 1:n() - 1)

   user  weeks
   <chr> <dbl>
 1 A         1
 2 A         2
 3 A         3
 4 A         4
 5 A         5
 6 A         6
 7 B         4
 8 B         5
 9 B         6
10 B         7
11 B         8
12 B         9

Upvotes: 1

Related Questions