使用data.table的melt函数将多列宽格式数据转为长格式
使用data.table的melt高效转换多组成对列的宽表为长表
我完全懂你现在的痛点——如果手动拆分每一组testXX和testXXgr再用rbind合并,不仅写起来麻烦,数据量大的时候还特别低效。用data.table的melt函数可以一步搞定这个需求,而且性能拉满,完美适配这种多组成对列的场景。
完整实现步骤
首先确保你已经加载了data.table包,然后按以下步骤操作:
- 准备原数据并转为data.table格式
library(data.table) # 你的原数据代码(保持不变) id<-c("106E1258","106E2037","104E1182","105E1248","105E1470","10241247", "10241703") yr<-c(2017,2017,2015,2016,2016,2013,2013) finalgr<-c(72,76,75,71,75,77,78) test01<-c("R0560","R0066","R0308","R0129","R0354","R0483", "R0503") test01gr<-c(73,74,67,80,64,80,70) test02<-c("R0660","R0266","R0302","R0139","R0324","R0383" , "R0503") test02gr<-c(71,54,67,70,68,81,61) dt<-data.frame(id=id,yr=yr, finalgr=finalgr, test01=test01,test01gr=test01gr, test02=test02,test02gr=test02gr) # 转为data.table格式,适配melt函数 dt <- as.data.table(dt)
- 用melt函数完成宽转长
这一步是核心,重点是用patterns()参数批量匹配成对的列:
dt_long <- melt(dt, # 指定不需要转换的标识符列(每个长格式行都要保留的信息) id.vars = c("id", "yr", "finalgr"), # 用正则匹配成对的test和testgr列,同时指定转换后的列名 measure.vars = patterns(testid = "^test\\d+$", testgr = "^test\\d+gr$"), # 可选:标记当前行来自原数据的哪一组测试(比如1对应test01组) variable.name = "test_group", # 指定转换后值列的名称 value.name = c("testid", "testgr") ) # 如果不需要test_group列,直接删掉即可 dt_long[, test_group := NULL]
- 查看转换结果
运行后dt_long就是你想要的长格式数据,比如查看前4行:
dt_long[1:4]
输出结果和你给出的dt2结构完全一致,内容也对应:
id yr finalgr testid testgr 1: 106E1258 2017 72 R0560 73 2: 106E1258 2017 72 R0660 71 3: 104E1182 2015 75 R0308 67 4: 104E1182 2015 75 R0302 67
关键参数解释
id.vars:指定在转换过程中保持不变的列,也就是每个长格式行都要携带的标识符信息。measure.vars = patterns(...):这是处理多组成对列的灵魂!用正则表达式匹配列名:^test\\d+$匹配所有以test开头、后面跟数字的列(比如test01、test02)^test\\d+gr$匹配所有以test开头、数字结尾、最后加gr的列(比如test01gr、test02gr)- 括号里的
testid=和testgr=是直接给转换后的列命名,省去后续重命名的步骤。
variable.name:可选参数,用来标记当前行来自原数据的哪一组测试,不需要的话直接删除即可。
优势说明
这个方法最大的好处是扩展性极强——不管你后续新增多少组testXX和testXXgr列(比如test03、test03gr直到test100、test100gr),都不需要修改代码,正则表达式会自动匹配所有成对的列,比手动拆分合并高效太多,尤其是数据量较大时,data.table的melt性能远优于base R的方法。
内容的提问来源于stack exchange,提问作者changjx
相关产品推荐
相关产品推荐

