R语言宽格式数据转长格式:如何转换指定结构数据集得到目标长表
R语言宽格式转指定长格式代码调整方案
错误原因
你两次调用gather时没有将相同编号的LOC和OFF字段做匹配,不同编号的字段交叉组合产生了大量冗余数据,是多余行出现的核心原因。
推荐方案:使用tidyr的pivot_longer实现(官方已推荐用该函数替代旧版gather)
pivot_longer支持直接匹配列名中的分组信息,一步完成转换,代码更简洁不易出错:
# 加载依赖包 library(tidyverse) # 原始数据 example <- data.frame(RTD_1_LOC = c('A', 'B'), RTD_2_LOC = c('C', 'D'), RTD_3_LOC = c('E', 'F'), RTD_4_LOC = c('G', 'H'), RTD_5_LOC = c('I', 'J'),RTD_1_OFF = c('1', '2'), RTD_2_OFF = c('3', '4'), RTD_3_OFF = c('5', '6'), RTD_4_OFF = c('7', '8'), RTD_5_OFF = c('9', '10')) # 一步转换为目标格式 example2 <- example %>% pivot_longer( cols = everything(), # 选择所有列参与转换 # 正则匹配列名规则:RTD_【数字】_【LOC/OFF】 names_pattern = "RTD_(\\d+)_(LOC|OFF)", # 第一部分匹配结果存为RTD列,第二部分匹配的字段类型作为新列名,对应值存入对应列 names_to = c("RTD", ".value") ) %>% mutate(RTD = as.integer(RTD), OFF = as.integer(OFF)) # 转换为目标要求的数值格式
运行后得到的example2和你给出的目标结构完全一致。
原gather写法的修正方案
如果你需要沿用gather的写法,需要增加匹配相同RTD编号的逻辑避免交叉冗余:
library(tidyverse) # 转换LOC字段 ex_loc <- gather(example, key = "rtd_key", value = "LOC", RTD_1_LOC:RTD_5_LOC) %>% mutate(RTD = as.integer(sub("RTD_(\\d+)_LOC", "\\1", rtd_key))) %>% select(-rtd_key) # 转换OFF字段 ex_off <- gather(example, key = "rtd_key", value = "OFF", RTD_1_OFF:RTD_5_OFF) %>% mutate(RTD = as.integer(sub("RTD_(\\d+)_OFF", "\\1", rtd_key))) %>% select(-rtd_key) # 按RTD和原始行号匹配拼接 example2 <- ex_loc %>% group_by(RTD) %>% mutate(rowid = row_number()) %>% left_join(ex_off %>% group_by(RTD) %>% mutate(rowid = row_number()), by = c("RTD", "rowid")) %>% ungroup() %>% select(-rowid) %>% mutate(OFF = as.integer(OFF))
内容的提问来源于stack exchange,提问作者vizidea
相关产品推荐
相关产品推荐

