我有一个数据集,其中包含在不同诊所进行性传播感染测试的个人。我想让每个人在最终数据集中每 6 周只进行一次测试。
还有与此相关的类似问题 如此处所示。但是,我尝试使用此代码,但运行时间很长,因为我的数据集有超过 4000 万行。因此,我想使用 data.table,因为这通常更快。
请看一个可以使用的数据集:
library(tidyverse)
library(data.table)
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=as.data.frame(cbind(date, ID, clinic))
df=df %>% mutate(date=as.Date(date))
df=data.table(df)
在此示例中,我希望删除人员 A 在 2 月 7 日的测试和人员 E 在 1 月 10 日的测试。
这可以通过 reduction(
base::Reduce
或 purrr::reduce
)来完成:
df[, date := as.Date(date)] # since you have strings
df[, .SD[Reduce(function(kept, rn) c(kept, if (diff(date[c(kept[length(kept)], rn)]) >= 6*7) rn),
seq_len(.N)[-1], init=1),], ID]
# ID date clinic
# <char> <Date> <char>
# 1: A 2023-01-01 clinic1
# 2: A 2023-02-20 clinic1
# 3: B 2023-01-01 clinic2
# 4: B 2023-05-10 clinic2
# 5: C 2023-01-01 clinic3
# 6: D 2023-01-01 clinic4
# 7: D 2023-04-10 clinic4
# 8: E 2023-01-01 clinic6
匿名函数有两个参数:
kept
是之前要保留的“接受”位置(行索引),初始化为“1”;2:.N
(在一个组内),我们确定由 kept
索引的 last日期是否在
this日期的
6*7
天内,ala date[ kept[length(kept)] ]
是否在 date[ rn ]
的 42 天内;如果这是真的,那么我们将 rn
附加到 kept