R语言中多被试内因素数据框转宽及组差异提取咨询
我开展了一项包含3个被试内因素的实验,每个因素有2个水平,每个被试对应8种实验条件。当前我的数据框(df)包含1个id列、3个因素列和1个因变量列,前2个被试的数据示例如下:
Df <- data.frame(id = c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2), factor1 = c("A", "A", "A", "A", "B", "B","B","B","A", "A", "A", "A", "B", "B","B","B"), factor2 = c("x", "x", "y", "y", "x", "x", "y", "y","x", "x", "y", "y", "x", "x", "y", "y"), factor3 = c(4, 8, 4, 8, 4, 8, 4, 8,4, 8, 4, 8, 4, 8, 4, 8), dv = c(5.5, 4.1, 3.9, 2.7, NA, 9.9, 1.7, 5.2,3.0,2.8,2.2,8.0,9.9,2.6,0.1,3.0))我想要分析每个被试在特定因素组合下的因变量差异,例如factor1为"A"、factor2为"x"时,factor3水平4和8对应的dv差值。我认为可行的方法是先将数据框重组为每行对应一个被试、每列对应一种因素组合的格式,示例如下:
Df2 <- data.frame(id = c(1, 2), Ax4 = c(5.5, 3.0), Ax8 = c(4.1, 2.8), Ay4 = c(3.9, 2.2), Ay8 = c(2.7, 8.0), Bx4 = c(NA, 9.9), Bx8 = c(9.9, 2.6), By4 = c(1.7, 0.1), By8 = c(4.2, 3.0))请问该思路是否合理?若合理,如何在R中实现该转换?若不合理,提取每个被试因素组合间差异的替代方法是什么?
回答
思路合理性判断
你的思路完全合理!把长格式数据转换为宽格式(每行对应一个被试,每列对应一种因素组合),不仅能让你直观地对比每个被试在不同条件下的因变量值,还能方便后续快速计算特定组合间的差值,非常适配被试内设计的差异分析需求。
实现数据转换的方法
在R里有几种便捷的方式完成这个长转宽操作,这里推荐两种最常用的:
方法1:用tidyr包的pivot_wider()(推荐)
tidyr是tidyverse生态里的核心工具,语法清晰易读,处理这类结构转换非常顺手:
# 先安装并加载tidyr(如果没装过的话) # install.packages("tidyr") library(tidyr) # 先把三个因素拼接成你想要的列名格式(比如Ax4) Df$condition <- paste0(Df$factor1, Df$factor2, Df$factor3) # 转换为宽格式 Df2 <- pivot_wider(Df, id_cols = id, # 按id分组 names_from = condition,# 用拼接好的condition列作为新列名 values_from = dv) # 用dv列填充新列的值
运行后得到的Df2结构就和你给出的示例一致,注意原数据中被试1的By8值是5.2,你示例里写的4.2应该是笔误,代码会保留原始数据的正确值。
方法2:用基础R的reshape()函数
如果你不想加载额外包,基础R自带的reshape()也能实现:
# 直接转换为宽格式 Df2 <- reshape(Df, idvar = "id", timevar = c("factor1", "factor2", "factor3"), direction = "wide", sep = "") # 手动修改列名,去掉默认的前缀和分隔符 colnames(Df2) <- gsub("dv\\.|\\.", "", colnames(Df2))
计算因素组合间的差值
转换完成后,你就能轻松计算特定组合的差值,比如你提到的factor1=A、factor2=x时,factor3的4和8的差值:
Df2$Ax_diff <- Df2$Ax4 - Df2$Ax8
替代方法:直接在长格式数据中计算差值
如果不想转换数据格式,也可以直接在原始长格式数据里分组计算差值,这种方法更适合后续做统计检验(比如重复测量方差分析),推荐用dplyr包实现:
# 安装并加载dplyr(如果没装过) # install.packages("dplyr") library(dplyr) # 按id、factor1、factor2分组,计算factor3=4和8的dv差值 diff_df <- Df %>% group_by(id, factor1, factor2) %>% mutate(diff = dv[factor3 == 4] - dv[factor3 == 8]) %>% ungroup()
这样得到的diff_df是包含差值的长格式数据框,既保留了原始数据的结构,又能直接查看每个被试在不同factor1/factor2组合下的factor3水平差异,后续做统计分析也更灵活。
内容的提问来源于stack exchange,提问作者TanZor

