如何基于列名拆分数据,生成含DX/SX标识的结构化新行?
问题:拆分DX/SX相关列并生成带标识的多行数据
需求:通过列名将原始数据拆分为两行,分离DX与SX相关列,新增一列保留DX/SX标识;其中Num为关键字段,X为公共列,需保留在拆分后的同一份数据集中。
原始数据
a = read.table(text=" Num X STDX ABDX XBDX STSX ABSX XBSX 12 3 9 5 3 11 3 7 13 35 24 1 7 18 2 8 14 35 24 1 7 18 2 8 15 10 1 5 16 -10 5 3 ",h=T)
期望结果
b= read.table(text="Num X ST AB XB DX/SX 12 3 9 5 3 DX 12 3 11 3 7 SX 13 35 24 1 7 DX 13 35 18 2 8 SX 14 35 24 1 7 DX 14 35 18 2 8 SX 15 10 1 5 16 DX 15 10 -10 5 3 SX",h=T)
尝试的代码(存在合并问题)
c <- sapply(c("DX", "SX",""), function(x) a[endsWith(names(a),x)], simplify = FALSE)
问题:无法将Num和X列与DX/SX数据合并到同一数据集。
解决方案
方法1:使用tidyverse的pivot_longer(推荐)
利用tidyverse工具链可以一步完成列拆分、公共列合并与标识列添加:
library(tidyverse) result <- a %>% pivot_longer( cols = starts_with(c("ST", "AB", "XB")), names_to = c(".value", "DX/SX"), names_pattern = "(ST|AB|XB)(DX|SX)" ) %>% select(Num, X, ST, AB, XB, `DX/SX`) # 输出结果 print(result)
代码解释
cols = starts_with(c("ST", "AB", "XB")):选中所有需要拆分的目标列names_to = c(".value", "DX/SX"):.value表示将列名前缀(ST/AB/XB)作为新列名,DX/SX存储后缀标识names_pattern:用正则表达式匹配列名的前缀和后缀两部分select:调整列顺序与期望结果对齐
方法2:基础R的reshape函数
如果不想加载额外包,可以用基础R的reshape函数实现:
result_base <- reshape( a, direction = "long", varying = list(c("STDX", "STSX"), c("ABDX", "ABSX"), c("XBDX", "XBSX")), v.names = c("ST", "AB", "XB"), idvar = c("Num", "X"), times = c("DX", "SX"), timevar = "DX/SX" ) # 重置行名并调整列顺序 rownames(result_base) <- NULL result_base <- result_base[, c("Num", "X", "ST", "AB", "XB", "DX/SX")] print(result_base)
代码解释
direction = "long":将宽格式转为长格式varying:指定每组需要拆分的列对v.names:为拆分后的列命名idvar:指定需要保留的公共列(Num和X)times:设置标识列的取值timevar:指定标识列的列名
内容的提问来源于stack exchange,提问作者Inuraghe
相关产品推荐
相关产品推荐

