How do I add extra rows for all columns (except the grouping variable) for each group id in the data frame?
Data:
> library(tidyverse)
> df <- tibble(id = c("A", "B", "C"), day = c(3, 1, 2), station = c(10, 9, 2))
> df
# A tibble: 3 × 3
id day station
<chr> <dbl> <dbl>
1 A 3 10
2 B 1 9
3 C 2 2
Expected output:
# A tibble: 6 × 3
# Groups: id [3]
id day station
<chr> <dbl> <dbl>
1 A 2 9
2 A 3 10
3 B 0 8
4 B 1 9
5 C 1 1
6 C 2 2
I could change day using:
> df %>% group_by(id) %>% complete(day = (day - 1):day)
# A tibble: 6 × 3
# Groups: id [3]
id day station
<chr> <dbl> <dbl>
1 A 2 NA
2 A 3 10
3 B 0 NA
4 B 1 9
5 C 1 NA
6 C 2 2
But I couldn’t use mutate appropriately to do this for station as well as since I don’t know how to refer to each column inside complete properly:
Failed attempt:
> df %>%
+ group_by(id) %>%
+ mutate(across(c("day", "station"), complete((.x - 1):.x)))
>Solution :
This works for your desired output:
df %>% bind_rows(df %>% mutate(across(c('day', 'station'), ~.x - 1 ))) %>% arrange(id)
# A tibble: 6 × 3
# id day station
# <chr> <dbl> <dbl>
# 1 A 3 10
# 2 A 2 9
# 3 B 1 9
# 4 B 0 8
# 5 C 2 2
# 6 C 1 1
Explanation:
Here I’m appending the same dataframe but with mutated columns, so:
df %>% mutate(across(c('day', 'station'), ~.x - 1 ))
Is:
# A tibble: 3 × 3
id day station
<chr> <dbl> <dbl>
1 A 2 9
2 B 0 8
3 C 1 1
Then with bind_rows I’m appending those rows to the original dataframe, which brings:
# A tibble: 6 × 3
id day station
<chr> <dbl> <dbl>
1 A 3 10
2 B 1 9
3 C 2 2
4 A 2 9
5 B 0 8
6 C 1 1
Finally I just arrange by id so the rows look like your example