For a length-1 test (per group), you can use if(){} else{}
directly. Unlike vectorized functions like ifelse
, if_else
, and case_when
, the code in an if(){}
will only be evaluated if the condition is true.
myDf %>%
group_by(group) %>%
mutate(
v2010 = if(2010 %in% Year) value[Year == 2010] else NA,
v2011 = if(2011 %in% Year) value[Year == 2011] else NA
)
# # A tibble: 7 × 5
# # Groups: group [2]
# Year value group v2010 v2011
# <dbl> <dbl> <chr> <dbl> <dbl>
# 1 2010 0.233 A 0.233 NA
# 2 2012 -1.30 A 0.233 NA
# 3 2013 1.42 A 0.233 NA
# 4 2010 -0.685 B -0.685 0.718
# 5 2011 0.718 B -0.685 0.718
# 6 2012 0.447 B -0.685 0.718
# 7 2013 0.816 B -0.685 0.718
Of course, your operation doesn't generalize up well - if you want to do this for more than 1 or 2 columns it becomes repetitive and annoying to code. One alternative would be to filter, pivot, and join. By adjusting the filter
you can do this for 1 or many years with the same amount of code:
library(tidyr)
myDf |>
filter(Year %in% c(2010, 2011)) |>
pivot_wider(id_cols = group, names_from = Year, names_prefix = "v", values_from = value) |>
right_join(myDf)
# Joining with `by = join_by(group)`
# # A tibble: 7 × 5
# group v2010 v2011 Year value
# <chr> <dbl> <dbl> <dbl> <dbl>
# 1 A 0.233 NA 2010 0.233
# 2 A 0.233 NA 2012 -1.30
# 3 A 0.233 NA 2013 1.42
# 4 B -0.685 0.718 2010 -0.685
# 5 B -0.685 0.718 2011 0.718
# 6 B -0.685 0.718 2012 0.447
# 7 B -0.685 0.718 2013 0.816