如何在R中为科目组合与等级的所有组合生成可扩展统计列
解决方案
核心思路
通过定义可配置的科目类别映射和等级映射,结合tidyverse的批量处理函数,实现无需重复编写统计逻辑的可扩展方案。核心是把统计规则从硬编码改成配置式,新增类别/等级只需修改配置,不用改统计代码。
步骤1:定义可扩展的配置项
先把科目类别、等级对应关系做成可配置的变量,后续扩展直接修改这里:
library(tidyverse) # 科目类别映射:键是类别名称,值是匹配该类别的科目正则表达式 category_mapping <- list( eng_his = "english|history", # 人文科目 bio_math = "biology|math" # STEM科目 # 新增类别直接加行:比如 foreign_lang = "french|spanish" ) # 等级与字母对应:数字转字母等级 grade_map <- c("1" = "F", "2" = "D", "3" = "C", "4" = "B", "5" = "A") # 新增等级直接扩展:比如 "6" = "A+"
步骤2:处理原始数据,生成统计所需的中间字段
先给原始数据加上类别标签和字母等级,方便后续统计:
# 示例数据 student_grades <- tibble( student_id = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5), subject = c(rep(c("english", "biology", "math", "history"), 4), NA, "biology"), grade = c(1, 2, 3, 4, 5, 4, 3, 2, 2, 4, 1, 1, 1, 1, 2, 3, 3, 4) ) # 给每条成绩匹配所属类别、转换字母等级 grade_with_categories <- student_grades %>% mutate( # 匹配科目所属类别(NA表示不匹配任何类别) category = map_chr(subject, ~names(category_mapping)[str_detect(.x, category_mapping)] %>% first() %>% replace_na(NA)), # 转换为字母等级 letter_grade = recode(as.character(grade), !!!grade_map) )
步骤3:批量生成统计列
用pivot_wider统计每个学生在每个类别下的各等级次数,再转回长格式合并回原数据:
# 统计每个学生的类别-等级次数 category_grade_counts <- grade_with_categories %>% filter(!is.na(category), !is.na(letter_grade)) %>% count(student_id, category, letter_grade, name = "count") %>% # 把类别和等级合并成列名(比如eng_his_F) unite(col = "stat_col", category, letter_grade, sep = "_") %>% pivot_wider(names_from = stat_col, values_from = count, values_fill = 0) # 合并回原始数据集,保留长格式 final_result <- student_grades %>% left_join(category_grade_counts, by = "student_id")
结果展示
最终的final_result会保留原始长格式,同时新增所有[类别]_[等级]的统计列,比如eng_his_F、bio_math_A等,每个学生的每条成绩行都会显示该学生对应的统计次数。
扩展性说明
- 新增科目类别:只需在
category_mapping里添加一行,比如foreign_lang = "french|spanish",重新运行代码即可自动生成该类别的所有等级统计列。 - 新增等级:扩展
grade_map的键值对,比如"6" = "A+",代码会自动包含该等级的统计。 - 修改类别规则:直接修改
category_mapping里的正则表达式即可,比如把STEM改成"biology|math|chemistry"。
内容的提问来源于stack exchange,提问作者J.Sabree
相关产品推荐
相关产品推荐

