R语言实现将科目列转换为Subject行的格式化方法
问题
需要将以下原始数据表转换为特定格式:将表中的科目列(Math_sub、Eng_sub、Chem_sub)转换为新的Subject列中的行,每行仅保留对应科目的数值,其余科目列填充NA,同时保留ID与Year列。尝试使用reshape和tidyr库实现,但未得到预期输出,求可行解决方法。
原始数据
| ID | Year | Math_sub | Eng_sub | Chem_sub |
|---|---|---|---|---|
| 1 | 2010 | 20 | 15 | 12 |
| 1 | 2015 | 17 | 20 | 14 |
| 1 | 2016 | 13 | 17 | 12 |
| 3 | 2015 | 14 | 13 | NA |
| 3 | 2016 | 12 | 12 | NA |
| 5 | 2010 | 20 | 15 | 13 |
| 5 | 2015 | 17 | 20 | 14 |
| 5 | 2016 | NA | 17 | 12 |
| 9 | 2015 | 14 | 13 | NA |
| 9 | 2016 | 15 | 15 | 16 |
期望输出
| ID | Year | Math_sub | Eng_sub | Chem_sub | Subject |
|---|---|---|---|---|---|
| 1 | 2010 | 20 | NA | NA | Maths |
| 1 | 2010 | NA | 15 | NA | English |
| 1 | 2010 | NA | NA | 12 | Chemistry |
| 1 | 2015 | 17 | NA | NA | Maths |
| 1 | 2015 | NA | 20 | NA | English |
| 1 | 2015 | NA | NA | 14 | Chemistry |
| 1 | 2016 | 13 | NA | NA | Maths |
| 1 | 2016 | NA | 17 | NA | English |
| 1 | 2016 | NA | NA | 12 | Chemistry |
| 3 | 2015 | 14 | NA | NA | Maths |
| 3 | 2015 | NA | 13 | NA | English |
| 3 | 2015 | NA | NA | NA | Chemistry |
| 3 | 2016 | 12 | NA | NA | Maths |
| 3 | 2016 | NA | 12 | NA | English |
| 3 | 2016 | NA | NA | NA | Chemistry |
解决方法
可以结合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)
代码说明
- 科目映射:建立原数据列名与
Subject列显示名称的对应关系,确保输出的科目名称符合需求。 - 交叉连接:
cross_join会将原始数据的每一行与科目映射表的每一行组合,实现每个ID-Year对应三个科目行。 - 行内赋值:通过
rowwise()和ifelse判断,仅保留当前科目对应列的原始值,其余列填充NA。 - 列调整与排序:调整列顺序为期望的格式,并按ID、Year、Subject排序,保证输出结构整齐。
内容的提问来源于stack exchange,提问作者theD
相关产品推荐
相关产品推荐

