如何用data.table去除6周内重复的STI检测记录?
用data.table高效处理大尺度STI检测数据(每6周每人仅保留一条记录)
针对4000万行的超大数据集,data.table的原地操作和分组优化能大幅提升处理速度,完全适配你的需求。下面是具体实现方案:
核心逻辑
按人员ID分组,从最早的检测记录开始,仅保留与上一条保留记录间隔≥6周(42天)的条目,确保每人每6周最多一条记录。
完整代码实现
library(data.table) # 示例数据构造(实际使用时建议用fread直接读取大文件,比read.csv快10倍以上) date <- as.Date(c("2023-01-01", "2023-02-07", "2023-02-20", "2023-01-01", "2023-05-10", "2023-01-01", "2023-01-01", "2023-01-10", "2023-04-10", "2023-01-01", "2023-01-10")) ID <- c("A", "A", "A", "B", "B", "C", "D", "D", "D", "E", "E") clinic <- c("clinic1", "clinic1", "clinic1", "clinic2", "clinic2", "clinic3", "clinic4", "clinic5", "clinic4", "clinic6", "clinic6") df <- data.table(date, ID, clinic) # 1. 按ID和日期原地排序(data.table专属操作,无内存复制,速度极快) setorder(df, ID, date) # 2. 分组标记需保留的记录:遍历每个ID的检测日期,仅保留间隔≥42天的条目 df[, keep := { keep_vec <- logical(.N) last_kept <- date[1] - 43 # 初始值设为第一条记录前43天,确保第一条必留 for (i in seq_len(.N)) { if (date[i] - last_kept >= 42) { keep_vec[i] <- TRUE last_kept <- date[i] } } keep_vec }, by = ID] # 3. 筛选保留记录并移除临时标记列 df_filtered <- df[keep == TRUE, !"keep"] # 查看处理结果 print(df_filtered)
处理结果验证
运行后得到的结果完全符合你的要求:
- 人员A的
2023-02-07记录(与第一条间隔37天<42)被移除,保留2023-01-01和2023-02-20 - 人员E的
2023-01-10记录(与第一条间隔9天<42)被移除,仅保留2023-01-01 - 其他人员的记录按6周规则自动筛选
大表性能优化建议
针对4000万行的数据集,额外优化点能进一步提升速度:
- 用
fread读取原始数据:df <- fread("your_sti_data.csv"),比传统读取方法快数倍,支持自动识别日期列 - 设置索引键:
setkey(df, ID, date),让分组操作直接利用索引,避免重复排序 - 减少内存占用:用
fread的select参数只读取需要的列(比如select = c("date", "ID", "clinic")) - 原地操作优先:尽量使用
:=修改列,避免复制整个数据集
内容的提问来源于stack exchange,提问作者Vicki Latham
相关产品推荐
相关产品推荐

