r - 在应用函数时有条件地合并两个 data.tables 的最有效方法
问题描述
我有随时间cohort_D0_multvis
变化的遇到日期(即 CONTACT_DATE
对于每个CONTACT_DATE
我想保留最接近但严格低于相遇日期的实验室测量值。我还想保留任何没有任何实验室数据或不符合上述句子逻辑的记录的记录。
我能够在调节时将随时间变化的遭遇日期cohort_D0_multvis
的 data.table 与实验室数据的 data.tableA1c
合并CONTACT_DATE>LAB_DATE
,如下所示:
条件合并:
test <- cohort_D0_multvis[unique(A1c)
, on = .(ID, CONTACT_DATE > LAB_DATE)
, nomatch = 0
, .(ID, CONTACT_DATE = x.CONTACT_DATE, LAB_DATE, A1c)]
接下来,我创建了一个新列test[,date_diff:=as.numeric(CONTACT_DATE-LAB_DATE)
,然后用于.SD[which.min(date_diff)]
保留最接近相遇日期的实验室测量值。最后,我将剩余的记录合并回我的遭遇数据中,以引入任何可能由于上述条件逻辑而被删除的记录,如下所示:
中间步骤:
test[,date_diff:=as.numeric(CONTACT_DATE-LAB_DATE)]
test <- test[,.SD[which.min(date_diff)],by=.(ID,CONTACT_DATE)]
test <- merge(test,cohort_D0_multvis,by=c("ID","CONTACT_DATE"),all.y = TRUE)
最终数据集:
### This is exactly what I want
ID CONTACT_DATE LAB_DATE A1c date_diff
1: A 2002-01-26 2000-09-30 4.938065 483
2: A 2004-10-26 2000-09-30 4.938065 1487
3: A 2006-09-01 2000-09-30 4.938065 2162
4: A 2014-05-23 2007-12-08 6.170197 2358
5: A 2017-01-28 2007-12-08 6.170197 3339
6: A 2020-04-16 2007-12-08 6.170197 4513
7: B 1998-03-02 <NA> NA NA
8: B 2003-05-08 <NA> NA NA
9: B 2004-09-27 2003-10-14 7.071354 349
10: B 2008-11-05 2007-06-04 5.173654 520
11: B 2015-11-24 2014-06-03 6.100639 539
12: C 1993-08-30 <NA> NA NA
13: C 1993-10-04 <NA> NA NA
14: C 1996-07-01 1995-07-28 5.852059 339
15: C 1996-11-08 1995-07-28 5.852059 469
16: C 1999-02-19 1995-07-28 5.852059 1302
17: C 2012-01-03 2005-03-16 6.640102 2484
18: C 2020-05-17 2018-11-23 4.729267 541
但是,我正在使用的实际遭遇数据和实验室数据有超过 130 万条记录,上面的条件合并将导致输出具有重复的唯一遭遇,每个唯一的实验室记录按 ID(即,超过 nrow(x)+ nrow(i) 行)。我必须重复这个过程大约 10 次(即,将大约 10 个实验室数据集合并到遇到数据集),这将非常耗费时间和内存。
我的问题:
- 在进行条件合并时,是否有一种更有效的方法可以到达我的最终数据集,而不必创建具有多于 nrow(x)+nrow(i) 行的数据集?
非常感谢任何建议或帮助。下面是重现我的输出的代码。
可重现的例子:
library(data.table)
library(lubridate)
### Create sample cohort with screening dates
set.seed(1992)
cohort_D0_multvis <- data.table(ID=c(rep("A",6),rep("B",5),rep("C",7)),
CONTACT_DATE=c(sample(seq(as_date('1992/01/01'), as_date('2021/06/04'), by="day"), 6),
sample(seq(as_date('1992/01/01'), as_date('2021/06/04'), by="day"), 5),
sample(seq(as_date('1992/01/01'), as_date('2021/06/04'), by="day"), 7)))
setkeyv(cohort_D0_multvis,c("ID","CONTACT_DATE"))
cohort_D0_multvis
### Create sample a1c data with lab dates
set.seed(304)
A1c <- data.table(ID=c(rep("A",6),rep("B",5),rep("C",7)),
LAB_DATE=c(sample(seq(as_date('1992/01/01'), as_date('2021/06/04'), by="day"), 6),
sample(seq(as_date('1992/01/01'), as_date('2021/06/04'), by="day"), 5),
sample(seq(as_date('1992/01/01'), as_date('2021/06/04'), by="day"), 7)),
A1c=rnorm(18,5.7,1))
setkeyv(A1c,c("ID","LAB_DATE"))
A1c
### For every CONTACT_DATE we want to retain the lab measurement that occurs closest to, but strictly lower, than the screening date
test <- cohort_D0_multvis[unique(A1c)
, on = .(ID, CONTACT_DATE > LAB_DATE)
, nomatch = 0
, .(ID, CONTACT_DATE = x.CONTACT_DATE, LAB_DATE, A1c)]
test[,date_diff:=as.numeric(CONTACT_DATE-LAB_DATE)]
test <- test[,.SD[which.min(date_diff)],by=.(ID,CONTACT_DATE)]
# Bring back patients w/o lab data
test <- merge(test,cohort_D0_multvis,by=c("ID","CONTACT_DATE"),all.y = TRUE)
test
解决方案
推荐阅读
- laravel - 如何在使用 axios 从 API 获取数据时更新我的 VueJs Data 函数属性值?
- python - 将多行结果转换为文件中 txt 文件的单行
- python - 从 txt 文件记录 URL
- python - 从 Python 中的嵌套列表制作直方图
- c# - DevExpress GridView for MVC - 如何设置模板单元格的默认值
- java - Android:切换纵向和横向时保存和恢复活动数据
- javascript - Plesk Obsidian、IISNode 和 Express 问题 - 应用程序只能在本地运行
- swift - Swift != 在 switch 语句中
- sql-server - 创建这些表的正确方法是什么?
- sql - 填充 CartesianChart 时,对象不能从 DBNULL 转换为其他类型异常