在R中如何对含多可变变量的宽格式数据集做长格式重塑?
在R中重塑多变量宽格式数据为长格式
问题背景
你的宽格式数据集包含多组嵌套变量:
- 固定变量:
pptns(参与者ID)、educ(教育水平) - 面积测量:分
exp/CTRL两种条件,3种工具(1/2/3),before/after两个时间点,共12个变量(如area_exp_1_before) - 心率(HR)测量:分
exp/CTRL两种条件,before/during/after三个时间点,共6个变量(如HR_exp_before)
需要将这类多维度的宽数据转换为适合统计建模的长格式,以下是两种可行方案:
推荐方案:使用tidyr::pivot_longer
tidyr包的pivot_longer适合处理多维度变量名的拆分,比基础R的reshape更灵活直观。
1. 模拟宽格式数据(可复现)
先生成和你场景匹配的模拟数据:
library(tidyverse) set.seed(123) wide_data <- tibble( pptns = 1:5, educ = sample(c("高中", "本科", "研究生"), 5, replace = TRUE), # 面积测量变量 area_exp_1_before = rnorm(5, 10, 2), area_exp_2_before = rnorm(5, 12, 2), area_exp_3_before = rnorm(5, 11, 2), area_exp_1_after = rnorm(5, 15, 2), area_exp_2_after = rnorm(5, 16, 2), area_exp_3_after = rnorm(5, 14, 2), area_CTRL_1_before = rnorm(5, 10, 2), area_CTRL_2_before = rnorm(5, 12, 2), area_CTRL_3_before = rnorm(5, 11, 2), area_CTRL_1_after = rnorm(5, 13, 2), area_CTRL_2_after = rnorm(5, 14, 2), area_CTRL_3_after = rnorm(5, 12, 2), # 心率变量 HR_exp_before = rnorm(5, 70, 5), HR_exp_during = rnorm(5, 85, 5), HR_exp_after = rnorm(5, 75, 5), HR_CTRL_before = rnorm(5, 70, 5), HR_CTRL_during = rnorm(5, 82, 5), HR_CTRL_after = rnorm(5, 73, 5) )
2. 执行重塑
利用正则表达式匹配变量名的结构,一次性拆分所有维度:
long_data <- wide_data %>% pivot_longer( cols = -c(pptns, educ), # 保留固定变量,其余全部重塑 names_to = c("measure_type", "condition", "temp", "time_point"), names_pattern = "(area|HR)_(exp|CTRL)_(\\d+|before|during|after)_(before|after)?", values_to = "value" ) %>% # 清理临时列:心率没有工具,把temp列的值转到time_point mutate( time_point = ifelse(measure_type == "HR", temp, time_point), tool = ifelse(measure_type == "area", temp, NA) ) %>% select(-temp) %>% # 调整列顺序,方便查看 select(pptns, educ, measure_type, condition, time_point, tool, value)
最终长格式结构
每一行对应一个参与者的单次测量,列定义:
pptns:参与者IDeduc:教育水平(固定变量)measure_type:测量类型(area/HR)condition:实验条件(exp/CTRL)time_point:测量时间点(before/during/after,面积无during)tool:面积测量使用的工具(心率测量为NA)value:测量的数值
替代方案:基础R的reshape函数
如果依赖基础R环境,可分两步处理面积和心率变量,再合并:
# 处理面积变量 long_area <- reshape( wide_data, direction = "long", varying = grep("area_", names(wide_data), value = TRUE), idvar = "pptns", timevar = "var", v.names = "value", sep = "_" ) %>% separate(var, into = c("measure_type", "condition", "tool", "time_point"), sep = "_") %>% select(pptns, educ, measure_type, condition, tool, time_point, value) # 处理心率变量 long_hr <- reshape( wide_data, direction = "long", varying = grep("HR_", names(wide_data), value = TRUE), idvar = "pptns", timevar = "var", v.names = "value", sep = "_" ) %>% separate(var, into = c("measure_type", "condition", "time_point"), sep = "_") %>% mutate(tool = NA) %>% select(pptns, educ, measure_type, condition, tool, time_point, value) # 合并两个数据集 long_data_base <- rbind(long_area, long_hr)
内容的提问来源于stack exchange,提问作者Marjolijn
相关产品推荐
相关产品推荐

