验证R语言data.table中shift函数使用及考试统计逻辑是否正确
问题解答:统计连续两次不及格后再次不及格的次数
问题描述
我有一份学生多次考试的数据集,其中“不及格”标记为0,“及格”标记为1。数据按学生ID和考试日期排序,需求是统计每个学生在连续两次考试不及格后,再次不及格的次数。
数据集示例生成代码:
# Load the data.table package library(data.table) # Generate some sample data id = sample.int(10000, 100000, replace = TRUE) res = c(1,0) results = sample(res, 100000, replace = TRUE) date_exam_taken = sample(seq(as.Date('1999/01/01'), as.Date('2020/01/01'), by="day"), 100000, replace = TRUE) # Create a data table from the sample data my_data = data.table(id, results, date_exam_taken) my_data <- my_data[order(id, date_exam_taken)] # Generate some additional columns for each record my_data$general_id = 1:nrow(my_data) my_data$exam_number = ave(my_data$general_id, my_data$id, FUN = seq_along) my_data$general_id = NULL
现有实现的问题
你的代码存在两个核心问题:
shift()未按学生分组:当前shift(my_data$results, 1)是对整个数据集做偏移,没有按id分组,会导致不同学生的考试结果被错误关联(比如学生A的最后一次结果会被当成学生B的前一次结果)。- 统计逻辑偏离需求:你统计了前1-3次考试结果的所有组合出现次数,但需求只关注「前两次都是0,本次也是0」的特定场景,不需要额外组合的统计。
正确的data.table实现方案
步骤1:按学生分组生成前序考试结果
确保shift()在每个学生的考试序列内执行,用by=id分组操作:
# 按id分组,生成前1次、前2次的考试结果 my_data[, `:=`( prev1 = shift(results, 1), prev2 = shift(results, 2) ), by = id]
步骤2:筛选条件并统计次数
筛选出「前两次不及格(0)且本次也不及格(0)」的记录,再按学生ID统计次数:
# 统计每个学生符合条件的次数 result <- my_data[prev1 == 0 & prev2 == 0 & results == 0, .(count = .N), by = id] # 查看结果示例 head(result)
补充说明
- 上述代码会覆盖所有符合场景的情况:比如连续3次不及格的序列中,第3次会被统计;连续4次不及格的序列中,第3、4次都会被统计。
- 使用
:=是data.table的高效修改方式,避免生成额外数据副本,更符合data.table的最佳实践。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

