#r #merge #data.table #cartesian-product #processing-efficiency
Вопрос:
У меня есть большие данные.таблица cohort_D0_multvis
изменяющихся во времени дат встреч (т. Е. CONTACT_DATE
), и я хочу объединить эти данные.таблица с несколькими наборами лабораторных данных, также большими данными.таблица; для каждого CONTACT_DATE
я хочу сохранить лабораторное измерение, которое происходит ближе всего, но строго ниже, чем дата встречи. Я также хочу сохранить любые записи без каких-либо лабораторных данных или записей, которые не соответствовали логике вышеупомянутого предложения.
Мне удалось объединить данные.таблицу дат встреч , изменяющихся во времени cohort_D0_multvis
, с данными.таблицей лабораторных данных A1c
во время кондиционирования 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
Однако фактические данные о встречах и лабораторные данные, с которыми я работаю, содержат более 1,3 миллиона записей, и приведенное выше условное объединение приведет к выходу с дублированными уникальными встречами, каждая уникальная лабораторная запись по идентификатору (т. Е. Более nrow(x) nrow(i) строк). Мне придется повторить этот процесс около 10 раз (т. Е. Объединить около 10 наборов лабораторных данных с набором данных о встрече), что потребует очень много времени и памяти.
Мой вопрос:
- Существует ли более эффективный способ получить мой окончательный набор данных без необходимости создавать набор данных с более чем nrow(x) nrow(i) строк при выполнении условного слияния?
Мы будем очень признательны за любой совет или помощь. Ниже приведен код для воспроизведения моего вывода.
Reproducible Example:
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