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

如何在R/exams的nops_eval结果中自动识别题型分组并计算分数?

我非常喜欢使用R/exams——在给约200名学生评分时,它是最节省时间的工具。

背景

我使用exams2nops()生成纸质试卷,每份试卷包含两部分:

  • 授课模块(Lecture section)——30道加权单选题(分值1至4分)。
  • 研讨模块(Seminar section)——15道加权单选题。

评分时我需要:

  • 30道授课模块题目的总分,
  • 15道研讨模块题目的总分,
  • 通过公式0.70 × 授课模块总分 + 0.30 × 研讨模块总分计算最终成绩。

问题

运行nops_eval()后,我得到一个数据框,每道题目对应一列(列名从points.1到points.45)。如何通过程序化方式识别哪些列属于授课模块、哪些属于研讨模块,而非硬编码列名?

当前(手动)解决方案:

library(dplyr)

result <- data_frame %>% 
  filter(exam == 25062200004) %>%                 # 选择某一试卷版本
  select(starts_with("points."), name, id) %>% 
  mutate(
    pct_seminar = rowSums(across(c(points.2, points.7, points.8, points.9,
                                   points.10, points.15, points.18, points.21,
                                   points.24, points.27, points.33, points.35,
                                   points.37, points.38, points.45))),
    total_points = rowSums(across(points.1:points.45)),
    pct_course  = total_points - pct_seminar + if_else(id %in% exp_ids, 0.5, 0)
  )

程序化解决方案

核心思路是从试卷生成阶段的元数据中提取题目分组信息,彻底替代硬编码列名的操作:

1. 保留试卷生成时的元数据

调用exams2nops()时,务必保存完整返回结果,其中包含每道题的配置信息:

# 生成试卷时保存完整输出(含元数据)
nops_output <- exams2nops(
  questions = your_question_list,  # 你的题目列表
  n = 1,  # 按需调整试卷版本数量
  dir = "output",
  meta = TRUE  # 开启元数据保存
)

2. 构建题目分组与列名的映射

根据题目模块的划分规则(按顺序或标签),生成分组与points.*列的对应关系:

  • 按题目顺序划分:如果前30道是授课模块、后15道是研讨模块,直接生成映射:
question_groups <- c(rep("lecture", 30), rep("seminar", 15))
points_cols <- paste0("points.", seq_along(question_groups))

group_col_map <- tibble(
  col_name = points_cols,
  group = question_groups
)
  • 按题目标签划分:如果出题时给每个题目添加了tags: lecture/tags: seminar标签,直接从元数据提取:
# 从元数据中读取每道题的标签
question_tags <- sapply(nops_output$meta$question, function(q) q$tags)
group_col_map <- tibble(
  col_name = paste0("points.", seq_along(question_tags)),
  group = question_tags
)

3. 动态计算各模块总分

用映射结果筛选列,完成评分计算:

library(dplyr)

# 提取两个模块对应的列名
lecture_cols <- group_col_map %>% filter(group == "lecture") %>% pull(col_name)
seminar_cols <- group_col_map %>% filter(group == "seminar") %>% pull(col_name)

result <- data_frame %>% 
  filter(exam == 25062200004) %>% 
  select(all_of(c(points_cols, "name", "id"))) %>% 
  mutate(
    pct_seminar = rowSums(across(all_of(seminar_cols))),
    pct_course = rowSums(across(all_of(lecture_cols))) + if_else(id %in% exp_ids, 0.5, 0),
    final_score = 0.7 * pct_course + 0.3 * pct_seminar  # 计算最终成绩
  )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 19:34:58