如何使用dcast将长表按多列转换为指定宽表格式?
解决dcast转换长表到宽表的格式问题
示例数据
首先生成问题中的长表数据:
# 生成示例数据 ID <- c('a','a','a','b','b','b') Parameter <- c('p1','p2','p3','p1','p2','p3') Value <- c('yes','no','3','yes','yes','2') Comment <- c(NA,'Deduced','To verify',NA,'Deduced','Verified') Source <- c('Exp.1','Exp.1','Exp.1+2','DB2','DB2','DB2') Person <- c('X','X','X','Y','Y','Z') long.data <- data.frame(ID,Parameter,Value,Comment,Source,Person)
预期输出
需要将上述长表转换为以ID和Person为分组列,每个Parameter对应Value、Comment、Source三个字段的宽表:
ID Person p1 p1-Comment p1-Source p2 p2-Comment p2-Source p3 p3-Comment p3-Source 1 a X yes <NA> Exp.1 no Deduced Exp.1 3 To verify Exp.1+2 2 b Y yes <NA> DB2 yes Deduced DB2 2 Verified DB2
可行解决方案
方法一:使用data.table的dcast(推荐)
利用data.table的灵活重塑功能,先将数据转为更长格式,再进行宽表转换:
library(data.table) # 将数据转为data.table对象 setDT(long.data) # 先将Value、Comment、Source转为变量列,实现“更长”的格式 melted_data <- melt(long.data, id.vars = c("ID", "Person", "Parameter"), measure.vars = c("Value", "Comment", "Source")) # 转换为宽表,按Parameter和variable组合列名 wide_data <- dcast(melted_data, ID + Person ~ Parameter + variable, sep = "-") # 调整列名:将p1-Value改为p1,去掉Value后缀 setnames(wide_data, gsub("-Value", "", names(wide_data)))
运行后即可得到预期的宽表结构。
方法二:使用tidyr的pivot_wider
如果熟悉tidyverse语法,也可以用pivot_wider实现:
library(tidyr) library(dplyr) wide_data <- long.data %>% # 转换为宽表,指定分组列、列名来源和值来源 pivot_wider( id_cols = c(ID, Person), names_from = Parameter, values_from = c(Value, Comment, Source), names_sep = "-" ) %>% # 重命名列,去掉Value后缀 rename_with(~ gsub("-Value", "", .x), starts_with("Value")) %>% # 调整列的顺序,匹配预期格式 select(ID, Person, p1, `p1-Comment`, `p1-Source`, p2, `p2-Comment`, `p2-Source`, p3, `p3-Comment`, `p3-Source`)
问题说明
之前使用dcast出错,大概率是因为未正确处理多值列(Value/Comment/Source)的映射,或是没有调整列名格式。上述两种方法都通过明确分组列、值来源列,再调整列名来匹配预期格式,避免无效列的生成。
内容的提问来源于stack exchange,提问作者David Inman
相关产品推荐
相关产品推荐

