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

R语言宽表转长表(含Stub变量):无需指定全部Stub实现转换

无需手动指定全部Stub,将带重复测量的宽格式数据转为长格式

问题背景

现有宽格式数据HAVE,变量名由时间标识前缀(如T/P)+时间数字+科目名称组成,需要转换为包含TIME列和各科目列的长格式数据WANT,且无需手动指定所有科目Stub。

原始与目标数据

宽格式输入(HAVE)

HAVE = data.frame(STUDENT=c(1,2),
                  CLASS = c(100,200),
                  T1CHE=c(95,NA),
                  T2CHE=c(13,66),
                  T3CHE=c(99,1),
                  T1CHES=c(81,NA),
                  T2CHES=c(43,59),
                  T3CHES=c(3,25),
                  P11MATH=c(56,88),
                  P12MATH=c(33,40),
                  P5MATHS=c(100,31),
                  P6MATHS=c(88,36),
                  T2ENG=c(37,63),
                  T3ENG=c(46,38),
                  T4ENG=c(14,74))

长格式目标(WANT)

WANT = data.frame(STUDENT=c(1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2),
                  CLASS = c(100,100,100,100,100,100,100,100,200,200,200,200,200,200,200,200),
                          TIME=c(1,2,3,4,5,6,11,12,1,2,3,4,5,6,11,12),
                          CHE=c(95,13,99,NA,NA,NA,NA,NA,NA,66,1,NA,NA,NA,NA,NA),
                          CHES=c(81,43,3,NA,NA,NA,NA,NA,NA,59,25,NA,NA,NA,NA,NA),
                          MATH=c(NA,NA,NA,NA,NA,NA,56,33,NA,NA,NA,NA,NA,NA,88,40),
                          MATHS=c(NA,NA,NA,NA,100,88,NA,NA,NA,NA,NA,NA,31,36,NA,NA),
                          ENG=c(NA,37,46,14,NA,NA,NA,NA,NA,63,38,74,NA,NA,NA,NA))

解决方案

使用tidyr的pivot_longer+pivot_wider组合,结合正则表达式自动拆分变量名中的时间和科目信息,无需手动枚举所有Stub:

library(tidyr)
library(dplyr)

# 转换数据
result <- HAVE %>%
  # 第一步:将测量变量转成长格式,提取时间标识和科目
  pivot_longer(
    cols = -c(STUDENT, CLASS),
    names_to = c("prefix", "TIME", "SUBJECT"),
    names_pattern = "^([A-Z])(\\d+)([A-Z]+)$",
    values_to = "score"
  ) %>%
  # 第二步:将科目转成列,对应各科目得分
  pivot_wider(names_from = SUBJECT, values_from = score) %>%
  # 移除无用的prefix列,转换TIME为数值型
  select(-prefix) %>%
  mutate(TIME = as.integer(TIME)) %>%
  # 补充所有需要的TIME值,填充缺失的得分
  complete(STUDENT, CLASS, TIME = c(1,2,3,4,5,6,11,12)) %>%
  # 按学生和时间排序,匹配目标数据顺序
  arrange(STUDENT, TIME)

# 验证结果是否与WANT一致
all.equal(result, WANT)

关键细节说明

  1. 正则表达式:^([A-Z])(\\d+)([A-Z]+)$ 精准拆分变量名:
    • ([A-Z]):匹配开头的T/P前缀
    • (\\d+):匹配时间数字(如1、11)
    • ([A-Z]+):匹配科目名称(如CHE、MATH)
  2. complete函数:确保所有指定的TIME值(1,2,3,4,5,6,11,12)都存在,缺失的得分自动填充为NA
  3. 排序:arrange(STUDENT, TIME) 保证结果顺序与WANT完全一致

运行代码后,result会和WANT完全匹配,all.equal(result, WANT)会返回TRUE。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:04:51