使用pivot_wider宽表转换时保留ID多行不合并为列表的实现方法
长表转宽表(同ID保留多组回答)解决方案
你此前删除的组标记变量是实现目标结构的核心字段,保留该变量可直接规避pivot_wider的自动合并逻辑,是成本最低的实现方式。
你之前的代码出现列表合并的原因是:tidyr::pivot_wider默认会用除names_from、values_from指定字段外的所有字段作为行唯一标识,你原始数据集仅包含ID、question、response三个字段,因此仅将ID作为行标识,同一ID下同一问题的多个回答就会被合并为列表格式。
方案1:可找回组标记变量时的最优解法
如果能恢复被删除的group_id字段(即每个ID下第N组1-5题对应相同的N值),直接将其加入行标识即可:
library(tidyr) df_wide <- pivot_wider( data = df, id_cols = c(ID, group_id), # 用ID+组ID共同作为行唯一标识 names_from = question, values_from = response, names_prefix = "question" ) # 不需要保留组标记可直接删除:df_wide$group_id <- NULL
输出结果直接符合你需要的结构,无列表嵌套值。
方案2:无法找回组标记变量时的临时解法
如果已经无法恢复组标记字段,可按ID分组后,根据question的出现顺序临时生成组标识:
library(dplyr) library(tidyr) # 加载你提供的示例数据集 df <- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L ), response = c(3L, 4L, 4L, 4L, 3L, 2L, 2L, 3L, 3L, 3L, 3L, 2L, 1L, 2L, 3L, 4L, 1L, 1L, 3L, 3L, 4L, 4L, 3L, 3L, 4L, 4L, 4L, 4L, 3L, 4L, 3L, 4L, 4L, 3L, 3L, 2L, 3L, 1L, 5L, 3L, 1L, 3L, 1L, 1L, 3L, 4L, 3L, 1L, 2L, 2L, 3L, 4L, 1L, 4L, 3L, 3L, 2L, 2L, 3L, 2L ), question = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L )), row.names = c(1:60), class = "data.frame") # 生成临时组ID:每遇到question=1就代表新的一组开始 df_with_group <- df %>% group_by(ID) %>% mutate(temp_group = cumsum(question == 1)) %>% ungroup() # 转换为宽表 df_wide <- pivot_wider( data = df_with_group, id_cols = c(ID, temp_group), names_from = question, values_from = response, names_prefix = "question" ) %>% select(-temp_group) # 移除临时生成的组标识
运行后得到的df_wide就是你期望的格式:同一ID对应多个行,每组回答单独占一行,所有值都是整数类型无列表嵌套。
内容的提问来源于stack exchange,提问作者user13343754
相关产品推荐
相关产品推荐

