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

验证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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:25:20