You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言将含被试内/被试间变量的宽DataFrame转为长表

问题背景

我正尝试从Excel表格构建长结构数据集,包含2个被试间变量和2个被试内变量,当前数据集结构如下:

> str(Subset_0)         
'data.frame':   54 obs. of  11 variables:
 $ Subject : num  1 2 3 4 5 6 7 8 9 10 ...
 $ BETWEEN1: num  1 1 1 2 2 2 2 1 1 2 ...
 $ BETWEEN2: num  1 1 2 2 2 2 1 1 1 1 ...
 $ A_x1    : num  5 1 3 1 0 6 1 2 7 1 ...
 $ B_x2    : num  5 1 3 0 3 0 0 2 6 1 ...
 $ C_y1    : num  6 9 9 2 2 4 2 2 6 0 ...
 $ D_y2    : num  6 15 4 1 2 4 3 1 3 0 ...
 $ K_x1    : num  5 1 3 1 0 6 1 2 7 1 ...
 $ L_x2    : num  5 1 3 0 3 0 0 2 6 1 ...
 $ M_y1    : num  6 9 9 2 2 4 2 2 6 14 ...
 $ N_y2    : num  3 1 0 4 0 5 6 5 17 21 ...

dput导出的数据集结构如下:

structure(list(Subject = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 
44, 45, 46, 47, 48, 49, 50, 51, 52, 54, 55), BETWEEN1 = c(1, 
1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 1, 1, 2, 2, 1, 
2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), BETWEEN2 = c(1, 
1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 
1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), A_x1 = c(5, 
1, 3, 1, 0, 6, 1, 2, 7, 1, 1, 0, 0, 2, 0, 8, NA, NA, NA, NA, 
14, 23, 19, 10, 9, 10, 11, 14, 16, 8, 24, 17, 8, 22, 14, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA), B_x2 = c(5, 1, 3, 0, 3, 0, 0, 2, 6, 1, 0, 0, 0, 0, 1, 
7, 14, 23, 19, 10, 14, 29, 15, 7, 13, 16, 7, 9, 17, 6, 7, 16, 
6, 11, 13, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA), C_y1 = c(6, 9, 9, 2, 2, 4, 2, 2, 6, 
0, 6, 0, 1, 10, 3, 8, 14, 29, 15, 7, 17, 21, 24, 7, 32, 31, 31, 
21, 27, 29, 18, 27, 33, 23, 28, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), D_y2 = c(6, 15, 
4, 1, 2, 4, 3, 1, 3, 0, 0, 0, 2, 2, 2, 5, 17, 21, 24, 7, 24, 
16, 28, 7, 28, 23, 25, 25, 24, 28, 33, 27, 31, 33, 21, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA), K_x1 = c(5, 1, 3, 1, 0, 6, 1, 2, 7, 1, 1, 0, 0, 2, 0, 8, 
24, 16, 28, 7, 24, 31, 31, 13, 32, 35, 32, 22, 29, 32, 32, 29, 
34, 32, 34, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA), L_x2 = c(5, 1, 3, 0, 3, 0, 0, 2, 6, 
1, 0, 0, 0, 0, 1, 7, 24, 31, 31, 13, 30, 30, 34, 12, 31, 27, 
23, 25, 33, 28, 31, 29, 30, 36, 24, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), M_y1 = c(6, 
9, 9, 2, 2, 4, 2, 2, 6, 14, 23, 19, 10, 9, 10, 11, 14, 16, 8, 
24, 17, 8, 22, 14, 33, 28, 31, 14, 23, 19, 10, 9, 10, 11, 14, 
16, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA), N_y2 = c(3, 1, 0, 4, 0, 5, 6, 5, 17, 21, 24, 7, 
32, 31, 31, 21, NA, NA, NA, NA, 27, 29, 18, 27, NA, NA, 17, 21, 
24, 7, 32, 31, 31, 21, 27, 17, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
-54L))

转换需求

需要按被试和条件拆分:A、B、C、D的值合并为一列命名为First,K、L、M、N的值合并为另一列命名为Second;变量名中的x、y对应被试内因子,存入新列Within1,_1、_2对应另一被试内因子,存入新列Within2,同时保留被试间因子列Between1和Between2,目标结构如下:

Subject First  Second  Within1  Within2 Between1 Between2
1         Ai     Ki        x        1          1        1 
1         Bi     Li        x        2          1        1 
1         Ci     Mi        y        1          1        1      
1         Di     Ni        y        2          1        1 
2         Ai     Ki        x        1          1        1 
2         Bi     Li        x        2          1        1 
2         Ci     Mi        y        1          1        1 
2         Di     Ni        y        2          1        1 
...

已完成操作与问题

我已经调用reshape函数完成了First列的合并和被试内变量的拆分,代码如下:

Subset_1 <-reshape(Subset_0, 
                   varying = c("A_x1", " B_x2", "C_y1", "D_y2"),
                   v.names = "First",
                   timevar = "Within1",
                   times =  c("A_x1", " B_x2", "C_y1", "D_y2"),
                   direction = "long")

# Next_Trial_Choice column
Subset_1$Within1[Subset_1$Within1== "A_x1"] <- "x"
Subset_1$Within1[Subset_1$Within1== "B_x2"] <- "x"
Subset_1$Within1[Subset_1$Within1== "C_y1"] <- "y"
Subset_1$Within1[Subset_1$Within1== "D_y2"] <- "y"

#cleaning the names - opponent column
Subset_1$Within2[Subset_1$Within2== "A_x1"] <- "1"
Subset_1$Within2[Subset_1$Within2== "B_x2"] <- "2"
Subset_1$Within2[Subset_1$Within2== "C_y1"] <- "1"
Subset_1$Within2[Subset_1$Within2== "D_y2"] <- "2"

现在我需要对Second列做同样的转换,对Subset_1再次调用reshape函数无法得到预期结果,请问有什么方法可以实现需求?


解决方法

方案1:基础R单次reshape完成转换

你不需要分两次调用reshape,这个函数本身支持同时处理多组测量值列,直接指定两组varying参数即可完成First和Second列的同步转换,避免多次reshape的行列匹配问题:

# 按顺序对应First和Second的原始列
Subset_final <- reshape(Subset_0,
                 varying = list(
                   c("A_x1", "B_x2", "C_y1", "D_y2"),
                   c("K_x1", "L_x2", "M_y1", "N_y2")
                 ),
                 v.names = c("First", "Second"),
                 timevar = "origin_col",
                 times = c("A_x1", "B_x2", "C_y1", "D_y2"),
                 direction = "long")

# 批量提取被试内因子,不需要逐行匹配赋值
Subset_final$Within1 <- ifelse(grepl("x", Subset_final$origin_col), "x", "y")
Subset_final$Within2 <- ifelse(grepl("_1", Subset_final$origin_col), "1", "2")

# 按需保留列、按被试排序
Subset_final <- Subset_final[,c("Subject", "First", "Second", "Within1", "Within2", "BETWEEN1", "BETWEEN2")]
Subset_final <- Subset_final[order(Subset_final$Subject),]

方案2:tidyverse方案(代码更简洁易维护)

如果允许使用第三方包,用pivot_longer实现逻辑更清晰,不需要记忆reshape的复杂参数:

library(tidyr)
library(dplyr)
library(stringr)

Subset_final <- Subset_0 %>%
  # 保留ID列和被试间变量,其余列全部转长
  pivot_longer(cols = -c(Subject, BETWEEN1, BETWEEN2),
               names_to = "col_name",
               values_to = "val") %>%
  # 拆分列名提取分组信息
  mutate(group = substr(col_name, 1, 1),
         Within1 = str_extract(col_name, "[xy]"),
         Within2 = str_extract(col_name, "[12]")) %>%
  # 把ABCD和KLMN组的值分别转成First和Second列
  pivot_wider(names_from = group, values_from = val) %>%
  rename(First = A, Second = K) %>%
  # 保留需要的列、排序
  select(Subject, First, Second, Within1, Within2, BETWEEN1, BETWEEN2) %>%
  arrange(Subject)

内容的提问来源于stack exchange,提问作者Camila Jones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 23:06:03