如何用pivot_longer处理变量命名不一致的宽表转长表?
解决变量名格式不一致的宽表转长表问题
针对你遇到的变量名后缀编号不统一、变量组长度不同的情况,可以通过「先转基础长表→提取变量组与编号→再转宽」的流程实现目标,具体代码如下:
完整处理代码
library(tidyr) library(dplyr) # 生成示例数据(你已有的代码) set.seed(1234) m <- matrix(sample(1:10, 75, replace = T), 5, 15) id <- 1:5 d <- cbind(id, as.data.frame(m)) names(d) <- c("id", "X1_hg", "X1_hg2", "X1_hg3", "X1_hg4", "cuphg_m01", "cuphg_m02", "cuphg_m03", "cuphg_m04", "cuphg_m05", "cuphg_v01", "cuphg_v02", "cuphg_v03", "cuphg_v04", "cuphg_v05", "cuphg_v06") # 宽转长核心流程 d_target <- d %>% # 第一步:将所有非id列转为基础长表 pivot_longer(-id, names_to = "var_name", values_to = "value") %>% # 第二步:提取变量组前缀和index编号 mutate( var_group = case_when( str_starts(var_name, "X1_hg") ~ "X1_hg", str_starts(var_name, "cuphg_m") ~ "cuphg_m", str_starts(var_name, "cuphg_v") ~ "cuphg_v" ), index = case_when( # X1_hg系列:无数字后缀的对应index=1,否则取末尾数字 str_starts(var_name, "X1_hg") ~ ifelse(var_name == "X1_hg", "1", str_extract(var_name, "\\d+$")), # cuphg_m/v系列:去掉前缀和前导零,提取数字 str_starts(var_name, "cuphg_m") ~ str_remove(var_name, "cuphg_m0?"), str_starts(var_name, "cuphg_v") ~ str_remove(var_name, "cuphg_v0?") ) %>% as.integer() ) %>% # 第三步:将变量组转为列,得到目标结构 pivot_wider(names_from = var_group, values_from = value) %>% # 按id和index排序(可选) arrange(id, index)
关键步骤说明
- 基础长表转换:先用
pivot_longer(-id)把所有非id列转为var_name(变量名)和value(变量值)的长表结构,统一处理变量名。 - 提取变量组与编号:
- 用
case_when根据变量名前缀区分三组变量; - 针对不同变量名格式单独提取index:X1_hg系列无后缀的对应index=1,cuphg_m/v系列去掉前导零后提取数字编号。
- 用
- 转宽得到目标结构:用
pivot_wider将变量组转为列,不同长度的变量组会自动用NA填充缺失值,符合你的需求。
通用优化方案(多变量组场景)
如果你的实际数据有更多变量组,可以用正则分支匹配一次性提取信息,避免重复写case_when:
d_target <- d %>% pivot_longer(-id, names_to = "var_name", values_to = "value") %>% mutate( # 正则分支匹配三种变量名模式 match_res = str_match(var_name, "^(X1_hg)(\\d*)$|^(cuphg_m)0?(\\d+)$|^(cuphg_v)0?(\\d+)$"), var_group = coalesce(match_res[,2], match_res[,3], match_res[,5]), index = coalesce( ifelse(match_res[,2] == "X1_hg" & is.na(match_res[,3]), 1, as.integer(match_res[,3])), as.integer(match_res[,4]), as.integer(match_res[,6]) ) ) %>% select(-match_res) %>% pivot_wider(names_from = var_group, values_from = value) %>% arrange(id, index)
内容的提问来源于stack exchange,提问作者dr_E
相关产品推荐
相关产品推荐

