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

如何在R中按分组优先级筛选并保留同日期最高测试得分记录?

问题描述

我有一个用于测试入学前课程效率的数据集,包含student_id、registration_id、subject、enrollment_date(入学日期)、test_date(测试日期)、test_score_category(测试得分等级)及difference(日期差)字段。需要按以下规则处理数据:

  • 分组优先级(1>2>3):
    1. 组1:入学前30天内(difference ∈ [-30, 0))
    2. 组2:入学后30天内(difference ∈ [0, 30])
    3. 组3:入学前45天至入学后35天内(difference ∈ [-45, -30) ∪ (30, 35])
  • 每个registration_id需归到优先级最高的对应组;
  • 同一学生同一天有多条测试记录时,保留test_score_category最高的记录;
  • 超出入学前45天至入学后30天范围的记录标记为未分类(用NA表示)。

原始数据集

data <- data.frame(
      student_id = c("a53e83bzz", "a53e83bzz", "a53e83bzz", "2034cccc", "2034cccc", "2034cccc", "2034cccc", "202353bbbb", "202353bbbb", "1980polkfbb", "1980polkfbb"),
 registration_id = c("a53-ffe9", "a53-ffe9", "a53-ffe9", "203-ffde", "203-ffde", "203-ffde", "203-ffde", "202-ffcc", "202-ffcc", "198-ffb", "198-ffb"),
 subject = c("maths", "maths", "maths", "maths", "maths", "maths", "maths", "english", "english", "english", "english"),
enrollment_date = as.Date(c("2021-02-28", "2021-02-28", "2021-02-28", "2019-03-25", "2019-03-25", "2019-03-25", "2019-03-25", "2021-05-22", "2021-05-22", "2019-07-04", "2019-07-04"), format="%Y-%m-%d"),
test_score_category = c(0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 2),
test_date = as.Date(c("2021-02-27", "2021-02-27", "2022-07-08", "2019-02-18", "2019-03-11", "2020-04-07", "2020-04-07", "2021-06-17", "2021-06-07", "2019-03-14", "2019-03-28"), format="%Y-%m-%d"),
difference = c(-1, -1, 495, -35, -14, 379, 379, 26, 16, -112, -98)
 )

尝试过的无效代码

result <- data %>%
group_by(student_id, registration_id) %>%
arrange(student_id, group) %>%  # Prioritize by group (1 > 2 > 3)
slice_max(order_by = test_score_category) %>%  
ungroup()

预期结果

df <- data.frame(
  student_id = c("a53e83bzz", "2034cccc", "202353bbbb", "1980polkfbb"),
  registration_id = c("a53-ffe9", "203-ffde", "202-ffcc", "198-ffb"),
  subject = c("maths", "maths", "english", "english"),
  enrollment_date = as.Date(c("2021-02-28", "2019-03-25", "2021-05-22", "2019-07-04"), format="%Y-%m-%d"),
  test_score_category = c(1, 0, 0, NA),  # Use NA for not_classified
  test_date = as.Date(c("2021-02-27", "2019-03-11", "2021-06-07", NA), format="%Y-%m-%d"),  # Use NA for not_classified
  difference = c(-1, -14, 16, NA)  # Use NA for not_classified
  )

正确的R实现方案

步骤说明

  1. 基于difference字段标记每条数据的分组优先级,超出范围的记录标记为最低优先级(0);
  2. 按registration_id分组,按「优先级降序→测试日期升序→得分降序」的逻辑排序,确保每组第一条是符合要求的记录;
  3. 提取每组第一条记录,将未分类记录的指定字段设为NA;
  4. 清理临时辅助列,得到最终结果。

完整代码

library(dplyr)

result <- data %>%
  # 标记分组优先级:1>2>3,超出范围标记为0(最低优先级)
  mutate(group_priority = case_when(
    between(difference, -30, -1) ~ 1,  # 入学前30天内
    between(difference, 0, 30) ~ 2,     # 入学后30天内
    between(difference, -45, -31) | between(difference, 31, 35) ~ 3,
    TRUE ~ 0  # 超出范围,未分类
  )) %>%
  # 按registration_id分组,按规则排序
  group_by(registration_id) %>%
  arrange(desc(group_priority), test_date, desc(test_score_category), .by_group = TRUE) %>%
  slice(1) %>%  # 取每组第一条符合要求的记录
  ungroup() %>%
  # 将未分类记录的指定字段设为NA
  mutate(
    across(c(test_score_category, test_date, difference), 
           ~ ifelse(group_priority == 0, NA, .x))
  ) %>%
  # 移除临时辅助列
  select(-group_priority)

# 查看结果
print(result)

代码解释

  • case_when标记优先级:严格匹配分组规则,未分类记录优先级设为0,确保后续排序时被排到最后;
  • 多条件排序:同一registration_id下,先保留高优先级组的记录;同组内取最早的测试记录;同一天的记录取得分最高的;
  • slice(1)提取目标记录:直接取每组排序后的第一条,即为符合所有规则的记录;
  • across批量处理NA:一次性将未分类记录的test_score_category、test_date、difference字段设为NA,简化代码;
  • 清理辅助列:移除临时的group_priority列,保证输出结构与预期一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:39:52