如何将患者多行数据的time_1、age_1等多变量转置为每位患者单行格式
数据长表转宽表问题
我拥有的数据集里,每位患者(对应id字段)因存在多个time_1和age_1取值,所以每位患者对应多行数据。我期望得到每位患者仅占一行的数据集,将其他行的time_1、age_1取值分别转置为time_2、time_3...以及age_2、age_3...等字段,同时需要保留原数据集中的所有字段。
原始数据示例
id ses_cd hbi sacro spondilo time_1 m_s_sacro age_1 1 0 0 0 0 126 0 43 1 0 0 0 0 158 0 45 1 0 0 0 0 223 0 22 2 0 0 0 1 140 1 51 2 0 0 0 1 358 1 98 2 0 0 0 1 140 1 35 3 0 0 0 0 75 0 39 3 0 0 0 0 76 0 75 3 0 0 0 0 258 0 88 3 0 0 0 0 856 0 45 4 0 0 0 0 30 0 31 4 0 0 0 0 30 0 33 4 0 0 0 0 30 0 55 4 0 0 0 0 12 0 65 5 0 0 0 0 212 0 49 6 0 0 1 0 10 1 42 7 1 1 0 0 20 0 19 8 0 0 0 0 3 0 51 9 1 1 0 1 8 0 30 10 1 0 0 0 0 0 34 11 1 1 0 0 93 0 27 12 0 0 0 0 5 0 20 13 1 1 0 0 2 0 61 14 0 0 0 0 44 0 24 15 0 0 0 0 0 0 55 16 0 0 0 0 166 0 42 17 1 1 0 1 1 1 35 18 1 0 0 0 1 0 29 19 0 0 0 0 204 0 60 20 0 0 0 1 0 0 66
已尝试代码
目前写的代码仅能实现单个变量的转置,无法支持多变量同时转置:
db %>% group_by(id, sacro) %>% summarise(time_1 = toString(time_1)) %>% separate(time_1, into = paste0("time_1", 1:5), sep = ", ", fill = "right", extra = "drop")
解决方案
使用tidyverse生态里的pivot_wider()函数可以轻松实现多变量同时转置,不需要单独处理每个字段:
library(tidyverse) result <- db %>% # 按患者id分组,为同id下的每条记录生成顺序编号 group_by(id) %>% mutate(visit_seq = row_number()) %>% ungroup() %>% # 转宽表 pivot_wider( # 同id下固定不变的字段会自动保留,无需手动列出也可正常运行 id_cols = c(id, ses_cd, hbi, sacro, spondilo, m_s_sacro), # 用刚才生成的访问序号作为字段后缀 names_from = visit_seq, # 此处可放入所有需要转置的变量,支持任意数量 values_from = c(time_1, age_1), # 自定义字段名格式,输出time_1、time_2... age_1、age_2...格式的字段 names_glue = "{str_remove(.value, '_1')}_{visit_seq}" )
说明
values_from参数支持传入任意数量的字段,后续需要新增转置变量直接添加到该参数的向量内即可- 无需手动指定最大转置数量,函数会自动根据患者最多的记录数生成对应字段,缺省值自动填充为NA
- 所有原始固定字段都会完整保留,符合需求
内容的提问来源于stack exchange,提问作者ArTu
相关产品推荐
相关产品推荐

