R:根据索引列查找两个日期中最接近的日期

时间:2019-10-16 20:00:09

标签: r date datetime

该项目的目的是测量医学实验室检查和最近用药之间的时间间隔。每个患者的后续服药剂量不同,每个受试者的随访实验室检查次数也不同。

第一个数据框包含study_id和相应的给药日期:

library(dplyr)
library(lubridate)

study_id<- c(1, 1, 1, 2, 2, 3)
dose_dt <- c('1/1/00', '2/1/00', '3/1/00', '1/1/01', '2/1/01', '1/1/02')
doses_df <- data.frame(study_id, dose_dt)
doses_df$dose_dt <- mdy(doses_df$dose_dt)
print(doses_df)

 study_id    dose_dt
1        1 2000-01-01
2        1 2000-02-01
3        1 2000-03-01
4        2 2001-01-01
5        2 2001-02-01
6        3 2002-01-01

第二个数据帧具有匹配的study_id,这次具有实验室检查日期和相关的实验室值以及异常指示(是/否)。

study_id <- c(1, 1, 1, 2, 3, 3, 3)
lab_dt <- c('1/1/99', '3/1/00', '4/1/00', '2/1/01', '2/1/02', '3/1/02', '4/1/02')
lab_result <- c(100, 200, 50, 25, 75, 100, 75)
lab_abn_yn <- c(0, 0, 1, 1, 1, 0, 1)
labs_df <- data.frame(study_id, lab_dt, lab_result, lab_abn_yn)
labs_df$lab_dt <- mdy(labs_df$lab_dt)
print(labs_df)

  study_id     lab_dt lab_result lab_abn_yn
1        1 1999-01-01        100          0
2        1 2000-03-01        200          0
3        1 2000-04-01         50          1
4        2 2001-02-01         25          1
5        3 2002-02-01         75          1
6        3 2002-03-01        100          0
7        3 2002-04-01         75          1

请注意,受试者1在第一次给药之前已经进行了一次实验室检查,受试者2的剂量比实验室检查的剂量大,受试者3的剂量少于实验室检查的剂量。

我希望R在实验室检查之前确定药物的最新剂量日期,以便我可以计算出剂量与实验室检查之间的间隔。输出将保留实验室值和指标。优选地,在第一剂之前的实验室检查(从剂量到实验室检查的负时间间隔)将被报告为NA,但我可以轻松过滤出负时间间隔。我也知道如何使用lubridate计算时间间隔,因此需要在解释中添加它。

所需的输出:

  study_id lab_dt     most_recent_dose_dt lab_result lab_abn_yn interval_months
     <dbl> <chr>      <chr>               <chr>           <dbl>           <dbl>
1        1 1999-01-01 NA                  NA                 NA          NA    
2        1 2000-03-01 2000-02-02          200                 0           0.966
3        1 2000-04-01 2000-03-01          50                  1           1    
4        2 2001-02-01 2001-01-01          25                  1           1    
5        3 2002-02-01 2002-01-01          75                  1           1    
6        3 2002-03-01 2002-01-01          100                 0           2    
7        3 2002-04-01 2002-01-01          75                  1           3      

我尝试了多种合并方案,但没有一个保留所有数据。大约有40,000个科目,因此手动进行是不可行的。任何帮助,不胜感激。

2 个答案:

答案 0 :(得分:2)

使用data.table连接,non-equi有一个单行解决方案:

library(data.table)
# create data.tables
labs_df <-  setDT(labs_df)
doses_df <- setDT(doses_df)

# create join variable
doses_df[,join_time := dose_dt]
labs_df[,join_time := lab_dt]

# do nonequi join with a condition
doses_df[labs_df,on=.(study_id,join_time < join_time),mult = "last"]

   study_id    dose_dt  join_time     lab_dt lab_result lab_abn_yn
1:        1       <NA> 1999-01-01 1999-01-01        100          0
2:        1 2000-02-01 2000-03-01 2000-03-01        200          0
3:        1 2000-03-01 2000-04-01 2000-04-01         50          1
4:        2 2001-01-01 2001-02-01 2001-02-01         25          1
5:        3 2002-01-01 2002-02-01 2002-02-01         75          1
6:        3 2002-01-01 2002-03-01 2002-03-01        100          0
7:        3 2002-01-01 2002-04-01 2002-04-01         75          1

这里的想法是,您正在将{_1}的study_idjoin_time的{​​{1}}和labs_df上的doses_df合并为labs_df。

我创建一个join_time列,因为联接只保留两个时间列之一,否则会更改名称,所以我总是会感到困惑:如果您直接这样做

joint_time

它给您

join_time

这对doses_df[labs_df,on=.(study_id,dose_dt < lab_dt),mult = "last"] 和其他列来说是正确的,但对 study_id dose_dt lab_result lab_abn_yn 1: 1 1999-01-01 100 0 2: 1 2000-03-01 200 0 3: 1 2000-04-01 50 1 4: 2 2001-02-01 25 1 5: 3 2002-02-01 75 1 6: 3 2002-03-01 100 0 7: 3 2002-04-01 75 1 列却造成了混乱,因为它变成了您进行合并的lab_result列(合并就像是子设置dose_dt值上的lab_dt列。

我实际上想在一开始使用滚动连接:

doses_dt

,但是问题在于它使日期等于或小于日期。

我使用this question查找了等联接解决方案,对于滚动联接,我建议使用this tutoriallab_dt速度很快,可让您在一行中实际完成所需的操作(合并中符合doses_df[labs_df,on=.(study_id,join_time),roll = T] study_id dose_dt join_time lab_dt lab_result lab_abn_yn 1: 1 <NA> 1999-01-01 1999-01-01 100 0 2: 1 2000-03-01 2000-03-01 2000-03-01 200 0 3: 1 2000-03-01 2000-04-01 2000-04-01 50 1 4: 2 2001-02-01 2001-02-01 2001-02-01 25 1 5: 3 2002-01-01 2002-02-01 2002-02-01 75 1 6: 3 2002-01-01 2002-03-01 2002-03-01 100 0 7: 3 2002-01-01 2002-04-01 2002-04-01 75 1 的最后一行)。

答案 1 :(得分:1)

我们可以分三个步骤进行操作:

  1. 过滤以仅保留实验室日期之后发生的剂量
  2. 过滤器仅保留每个实验室日期的最新剂量(由于使用了第一个过滤器,现在是最新剂量)
  3. 重新加入实验室列表,以重新包含之前未使用过的实验室日期

请注意,您的样本数据并不完全符合所需的打印结果,因为2月1日成为2月2日进行第二次观察。

library(tidyverse)
library(lubridate)
doses_df <- tibble(
  study_id = c(1, 1, 1, 2, 2, 3),
  dose_dt = mdy(c("1/1/00", "2/1/00", "3/1/00", "1/1/01", "2/1/01", "1/1/02"))
)
labs_df <- tibble(
  study_id = c(1, 1, 1, 2, 3, 3, 3),
  lab_dt = mdy(c("1/1/99", "3/1/00", "4/1/00", "2/1/01", "2/1/02", "3/1/02", "4/1/02")),
  lab_result = c(100, 200, 50, 25, 75, 100, 75),
  lab_abn_yn = c(0, 0, 1, 1, 1, 0, 1)
)

most_recent_doses <- labs_df %>%
  left_join(doses_df, by = "study_id") %>%
  group_by(study_id, lab_dt) %>%
  filter(dose_dt < lab_dt) %>%
  filter(dose_dt == max(dose_dt)) %>%
  select(study_id, lab_dt, dose_dt)

labs_df %>%
  left_join(most_recent_doses, by = c("study_id", "lab_dt")) %>%
  mutate(interval_months = interval(dose_dt, lab_dt) / months(1))
#> # A tibble: 7 x 6
#>   study_id lab_dt     lab_result lab_abn_yn dose_dt    interval_months
#>      <dbl> <date>          <dbl>      <dbl> <date>               <dbl>
#> 1        1 1999-01-01        100          0 NA                      NA
#> 2        1 2000-03-01        200          0 2000-02-01               1
#> 3        1 2000-04-01         50          1 2000-03-01               1
#> 4        2 2001-02-01         25          1 2001-01-01               1
#> 5        3 2002-02-01         75          1 2002-01-01               1
#> 6        3 2002-03-01        100          0 2002-01-01               2
#> 7        3 2002-04-01         75          1 2002-01-01               3

reprex package(v0.3.0)于2019-10-16创建

相关问题