Here are a couple of options. Let me know if these are on the right track.
# Set up fake data
library(tidyverse)
d = tribble(
~id, ~q1, ~q2, ~q3, ~v3, ~q4,
0, "a", "b", "x", 1, "c",
0, "a", "b", "y", 2, "c",
0, "a", "b", "z", 3, "c"
)
Option 1. In summarise
, return a list within a named list. The output is as requested in your example:
d2 = d %>%
group_by(across(-ends_with("3"))) %>%
summarise(qv3 = list(as.list(set_names(v3, q3))))
d2
# A tibble: 1 x 5 # Groups: id, q1, q2 [1] id q1 q2 q4 qv3 <dbl> <chr> <chr> <chr> <list> 1 0 a b c <named list [3]>
d2$qv3
[[1]] [[1]]$x [1] 1 [[1]]$y [1] 2 [[1]]$z [1] 3
# Recover the original data frame
d2 %>% unnest(qv3) %>% unnest(qv3)
Option 2. In this case, the nested objects are data frames with only one level of nesting:
d3 = d %>%
group_nest(across(-ends_with("3")), .key="qv3")
# group_nest() is experimental, but this is equivalent
d3 = d %>%
group_by(across(-ends_with("3"))) %>%
nest(qv3=c(q3, v3))
d3
id q1 q2 q4 qv3 <dbl> <chr> <chr> <chr> <list<tbl_df[,2]>> 1 0 a b c [3 × 2]
d3$qv3
<list_of< tbl_df< q3: character v3: double > >[1]> [[1]] # A tibble: 3 x 2 q3 v3 <chr> <dbl> 1 x 1 2 y 2 3 z 3
# Recover the original data frame
d3 %>% unnest(qv3)