R语言宽表转长表:无需指定TIME、TAB变量能否实现HAVE转WANT?
自动提取时变前缀实现数据重塑
现有R语言中的HAVE数据集与目标WANT数据集如下:
原始数据集(HAVE)
library(data.table) HAVE = fread(" STUDENT CLASS GROUP S1TIME S2TIME S3TIME H2TAB H4TAB H5TAB 1 0 2 NA NA 6 NA 7 5 2 0 7 4 NA 4 5 NA 2 3 1 5 NA 4 5 6 NA NA ")
目标数据集(WANT)
WANT = data.frame( STUDENT = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3), INPUT = c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5), CLASS = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1), GROUP = c(2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5), S.TIME = c(NA, NA, 6, NA, NA, 4, NA, 4, NA, NA, NA, 4, 5, NA, NA), H.TAB = c(NA, NA, NA, 7, 5, NA, 5, NA, NA, 2, NA, 6, NA, NA, NA) )
问题
能否在不指定TIME、TAB这类后缀关键词的前提下,将HAVE转换为WANT?希望自动提取时变前缀(stubs)并完成完整的数据重塑。
可以实现,核心思路是通过正则表达式自动识别变量名中的字母前缀(如S、H)和数字序号,先转长表拆分变量信息,再补全所有INPUT的完整序列,最后转回宽表。以下是两种可行方案:
方案1:使用data.table(适配原代码的fread)
library(data.table) # 1. 转长表,保留标识变量 long_dt = melt(HAVE, id.vars = c("STUDENT", "CLASS", "GROUP"), variable.name = "var", value.name = "val") # 2. 拆分变量名:分离字母前缀和数字INPUT编号 long_dt[, c("stub", "input") := tstrsplit(var, "(?<=[A-Za-z])(?=[0-9])", perl = TRUE)] long_dt[, input := as.integer(input)] long_dt[, var := NULL] # 3. 生成所有INPUT的完整组合(1-5),确保每个学生都有5行 full_inputs = CJ(STUDENT = unique(long_dt$STUDENT), INPUT = 1:5) # 4. 合并数据并转回宽表 result = merge(full_inputs, long_dt, by.x = c("STUDENT", "INPUT"), by.y = c("STUDENT", "input"), all.x = TRUE) result = dcast(result, STUDENT + INPUT + CLASS + GROUP ~ stub, value.var = "val") # 5. 重命名列以匹配目标格式,排序 setnames(result, c("S", "H"), c("S.TIME", "H.TAB")) setorder(result, STUDENT, INPUT)
方案2:使用tidyverse
library(tidyverse) HAVE %>% # 转长表 pivot_longer(cols = -c(STUDENT, CLASS, GROUP), names_to = "var", values_to = "val") %>% # 拆分变量名,自动转换数字类型 separate(var, into = c("stub", "input"), sep = "(?<=[A-Za-z])(?=[0-9])", convert = TRUE) %>% # 补全所有INPUT的行,缺失值填NA complete(STUDENT, INPUT = 1:5, fill = list(val = NA)) %>% # 转回宽表 pivot_wider(names_from = stub, values_from = val) %>% # 重命名列并排序 rename(S.TIME = S, H.TAB = H) %>% arrange(STUDENT, INPUT)
两种方案都无需手动指定TIME或TAB后缀,完全自动识别时变前缀,最终输出结构与WANT一致。
内容的提问来源于stack exchange,提问作者bvowe
相关产品推荐
相关产品推荐

