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

R语言实现将科目列转换为Subject行的格式化方法

问题

需要将以下原始数据表转换为特定格式:将表中的科目列(Math_sub、Eng_sub、Chem_sub)转换为新的Subject列中的行,每行仅保留对应科目的数值,其余科目列填充NA,同时保留ID与Year列。尝试使用reshape和tidyr库实现,但未得到预期输出,求可行解决方法。

原始数据

IDYearMath_subEng_subChem_sub
12010201512
12015172014
12016131712
320151413NA
320161212NA
52010201513
52015172014
52016NA1712
920151413NA
92016151516

期望输出

IDYearMath_subEng_subChem_subSubject
1201020NANAMaths
12010NA15NAEnglish
12010NANA12Chemistry
1201517NANAMaths
12015NA20NAEnglish
12015NANA14Chemistry
1201613NANAMaths
12016NA17NAEnglish
12016NANA12Chemistry
3201514NANAMaths
32015NA13NAEnglish
32015NANANAChemistry
3201612NANAMaths
32016NA12NAEnglish
32016NANANAChemistry
解决方法

可以结合dplyr和tidyr库实现需求,核心思路是通过交叉连接让每个ID-Year组合对应所有科目,再按行保留对应科目的数值:

library(dplyr)
library(tidyr)

# 定义科目名称与原列名的映射
subject_mapping <- tibble(
  Subject = c("Maths", "English", "Chemistry"),
  col_name = c("Math_sub", "Eng_sub", "Chem_sub")
)

# 处理数据
result <- df %>%
  # 让每一行ID-Year组合对应三个科目
  cross_join(subject_mapping) %>%
  # 按行判断,仅保留当前Subject对应列的原始值,其余设为NA
  rowwise() %>%
  mutate(
    Math_sub = ifelse(col_name == "Math_sub", Math_sub, NA),
    Eng_sub = ifelse(col_name == "Eng_sub", Eng_sub, NA),
    Chem_sub = ifelse(col_name == "Chem_sub", Chem_sub, NA)
  ) %>%
  ungroup() %>%
  # 调整列顺序并按ID、Year、Subject排序
  select(ID, Year, Math_sub, Eng_sub, Chem_sub, Subject) %>%
  arrange(ID, Year, Subject)

代码说明

  1. 科目映射:建立原数据列名与Subject列显示名称的对应关系,确保输出的科目名称符合需求。
  2. 交叉连接:cross_join会将原始数据的每一行与科目映射表的每一行组合,实现每个ID-Year对应三个科目行。
  3. 行内赋值:通过rowwise()和ifelse判断,仅保留当前科目对应列的原始值,其余列填充NA。
  4. 列调整与排序:调整列顺序为期望的格式,并按ID、Year、Subject排序,保证输出结构整齐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:10:00