使用 purrr 映射的日期嵌套循环
Nested loop on dates using purrr map
在临床试验中,假设我有:
(i) 剂量历史文件 ('dosing'),患者体内剂量增加,
(ii) 实验室参数值文件 ('lab'),在与给药事件日期不匹配的日期进行评估。
我想在实验室值文件中添加一列,其中包含在最后一次给药事件中收到的剂量。这是为分析实验室值做准备,其中剂量作为时变协变量输入。下面是使用 for
循环的相当原始的代码。
我们如何使用 purrr
包中的函数获得相同的数据帧(或 tibble)?
非常感谢!
library(tidyverse)
#' Dosing file
#' ----------------------------------
dosdatID1<-c("2020-06-06", "2020-06-15", "2020-06-22", "2020-07-07", "2020-07-17")
dosdatID2<-c("2020-06-05", "2020-06-08", "2020-06-24", "2020-06-27")
dosing<-data.frame(
ID=c(rep(1, 5), rep(2, 4)),
dosrec=c(1:5, 1:4),
doslev=c(c(0.1, 0.1, 0.1, 0.9, 0.9), c(0.2, 0.2, 0.3, 0.3)),
dosdat=as.Date(c(dosdatID1, dosdatID2)))
#' Lab values file
#' ----------------------------------
labdatID1<-c("2020-06-17", "2020-06-24", "2020-07-08")
labdatID2<-c("2020-06-06", "2020-06-26")
labs<-data.frame(
ID=c(rep(1, 3), rep(2, 2)),
labrec=c(1:3, 1:2),
labval=round(c(rnorm(3, 10, 5), rnorm(2, 15, 5)), 2),
labdat=as.Date(c(labdatID1, labdatID2))
)
labs$dos_current <- NA
# unique subject ID
u_subj<-unique(labs$ID)
# number of subjects
n_subj<-length(u_subj)
for(s in 1:n_subj){
# subset the labs dataset for one particular subject s
labs_1<-labs[which(labs$ID == u_subj[s]),]
# unique lab records for subject s
u_labrec <- unique(labs_1$labrec)
# number of unique lab records for this particular subject s
n_labrec <- length(u_labrec)
for(lb in 1:n_labrec){
# extract the date of this labrec
dt_labrec <- labs_1$labdat[which(labs_1$labrec == u_labrec[lb])]
### get the current dose from the dosing dataset
# subset the dosing dataset for one particular subject s
dosing_1 <- dosing[which(dosing$ID == u_subj[s]),]
# order the dates in decreasing order
dosing_1 <- dosing_1[ order(dosing_1$dosdat, decreasing = TRUE), ]
# get the latest dosing date which is less than or equal to the date of the labrec
doslev <- dosing_1$doslev[grep("TRUE", dosing_1$dosdat <= dt_labrec)[1]]
# input the current dose level into the labs dataset
labs$dos_current[which(labs$ID == u_subj[s] & labs$labrec == u_labrec[lb])] <- doslev
}
}
labs
抱歉,我没有 purrr
-solotion。但是在 data.table
上使用滚动连接会很快达到目的。
功能:
对于 labs
中的每一行。它将在 dosing
中找到与 labdat 之前相同的 ID
中的最后一个 dosdat,并将值 dosdat
和 doslev
添加到 labs
-data.table.
library( data.table )
#make them data.tables
setDT(dosing);setDT(labs)
#now rolling join by reference
labs[, c("dosdat", "doslev") := dosing[labs, .(dosdat = x.dosdat, doslev),
on = .(ID, dosdat = labdat),
roll = TRUE]][]
# ID labrec labval labdat dosdat doslev
# 1: 1 1 2.67 2020-06-17 2020-06-15 0.1
# 2: 1 2 16.62 2020-06-24 2020-06-22 0.1
# 3: 1 3 11.64 2020-07-08 2020-07-07 0.9
# 4: 2 1 8.85 2020-06-06 2020-06-05 0.2
# 5: 2 2 10.91 2020-06-26 2020-06-24 0.3
如果您正在寻找 tidyverse
解决方案,我建议您使用以下解决方案:
full_dosing <- dosing %>%
mutate(labdat = dosdat) %>%
group_by(ID) %>%
complete(labdat = seq(min(labdat), max(labdat), "day"), ID) %>%
fill(dosdat, dosrec, doslev) %>%
ungroup()
left_join(labs, full_dosing, by = c("ID", "labdat"))
ID labrec labval labdat dosrec doslev dosdat
1 1 1 4.92 2020-06-17 2 0.1 2020-06-15
2 1 2 2.89 2020-06-24 3 0.1 2020-06-22
3 1 3 14.01 2020-07-08 4 0.9 2020-07-07
4 2 1 3.92 2020-06-06 1 0.2 2020-06-05
5 2 2 17.58 2020-06-26 3 0.3 2020-06-24
但是,它的效率低于 data.table
解决方案,因为您需要先 complete
dosing
数据帧。
解决方案基于此数据:
#' Dosing file
#' ----------------------------------
dosdatID1<-c("2020-06-06", "2020-06-15", "2020-06-22", "2020-07-07", "2020-07-17")
dosdatID2<-c("2020-06-05", "2020-06-08", "2020-06-24", "2020-06-27")
dosing<-data.frame(
ID=c(rep(1, 5), rep(2, 4)),
dosrec=c(1:5, 1:4),
doslev=c(c(0.1, 0.1, 0.1, 0.9, 0.9), c(0.2, 0.2, 0.3, 0.3)),
dosdat=as.Date(c(dosdatID1, dosdatID2)))
#' Lab values file
#' ----------------------------------
labdatID1<-c("2020-06-17", "2020-06-24", "2020-07-08")
labdatID2<-c("2020-06-06", "2020-06-26")
labs<-data.frame(
ID=c(rep(1, 3), rep(2, 2)),
labrec=c(1:3, 1:2),
labval=round(c(rnorm(3, 10, 5), rnorm(2, 15, 5)), 2),
labdat=as.Date(c(labdatID1, labdatID2))
)
在临床试验中,假设我有:
(i) 剂量历史文件 ('dosing'),患者体内剂量增加,
(ii) 实验室参数值文件 ('lab'),在与给药事件日期不匹配的日期进行评估。
我想在实验室值文件中添加一列,其中包含在最后一次给药事件中收到的剂量。这是为分析实验室值做准备,其中剂量作为时变协变量输入。下面是使用 for
循环的相当原始的代码。
我们如何使用 purrr
包中的函数获得相同的数据帧(或 tibble)?
非常感谢!
library(tidyverse)
#' Dosing file
#' ----------------------------------
dosdatID1<-c("2020-06-06", "2020-06-15", "2020-06-22", "2020-07-07", "2020-07-17")
dosdatID2<-c("2020-06-05", "2020-06-08", "2020-06-24", "2020-06-27")
dosing<-data.frame(
ID=c(rep(1, 5), rep(2, 4)),
dosrec=c(1:5, 1:4),
doslev=c(c(0.1, 0.1, 0.1, 0.9, 0.9), c(0.2, 0.2, 0.3, 0.3)),
dosdat=as.Date(c(dosdatID1, dosdatID2)))
#' Lab values file
#' ----------------------------------
labdatID1<-c("2020-06-17", "2020-06-24", "2020-07-08")
labdatID2<-c("2020-06-06", "2020-06-26")
labs<-data.frame(
ID=c(rep(1, 3), rep(2, 2)),
labrec=c(1:3, 1:2),
labval=round(c(rnorm(3, 10, 5), rnorm(2, 15, 5)), 2),
labdat=as.Date(c(labdatID1, labdatID2))
)
labs$dos_current <- NA
# unique subject ID
u_subj<-unique(labs$ID)
# number of subjects
n_subj<-length(u_subj)
for(s in 1:n_subj){
# subset the labs dataset for one particular subject s
labs_1<-labs[which(labs$ID == u_subj[s]),]
# unique lab records for subject s
u_labrec <- unique(labs_1$labrec)
# number of unique lab records for this particular subject s
n_labrec <- length(u_labrec)
for(lb in 1:n_labrec){
# extract the date of this labrec
dt_labrec <- labs_1$labdat[which(labs_1$labrec == u_labrec[lb])]
### get the current dose from the dosing dataset
# subset the dosing dataset for one particular subject s
dosing_1 <- dosing[which(dosing$ID == u_subj[s]),]
# order the dates in decreasing order
dosing_1 <- dosing_1[ order(dosing_1$dosdat, decreasing = TRUE), ]
# get the latest dosing date which is less than or equal to the date of the labrec
doslev <- dosing_1$doslev[grep("TRUE", dosing_1$dosdat <= dt_labrec)[1]]
# input the current dose level into the labs dataset
labs$dos_current[which(labs$ID == u_subj[s] & labs$labrec == u_labrec[lb])] <- doslev
}
}
labs
抱歉,我没有 purrr
-solotion。但是在 data.table
上使用滚动连接会很快达到目的。
功能:
对于 labs
中的每一行。它将在 dosing
中找到与 labdat 之前相同的 ID
中的最后一个 dosdat,并将值 dosdat
和 doslev
添加到 labs
-data.table.
library( data.table )
#make them data.tables
setDT(dosing);setDT(labs)
#now rolling join by reference
labs[, c("dosdat", "doslev") := dosing[labs, .(dosdat = x.dosdat, doslev),
on = .(ID, dosdat = labdat),
roll = TRUE]][]
# ID labrec labval labdat dosdat doslev
# 1: 1 1 2.67 2020-06-17 2020-06-15 0.1
# 2: 1 2 16.62 2020-06-24 2020-06-22 0.1
# 3: 1 3 11.64 2020-07-08 2020-07-07 0.9
# 4: 2 1 8.85 2020-06-06 2020-06-05 0.2
# 5: 2 2 10.91 2020-06-26 2020-06-24 0.3
如果您正在寻找 tidyverse
解决方案,我建议您使用以下解决方案:
full_dosing <- dosing %>%
mutate(labdat = dosdat) %>%
group_by(ID) %>%
complete(labdat = seq(min(labdat), max(labdat), "day"), ID) %>%
fill(dosdat, dosrec, doslev) %>%
ungroup()
left_join(labs, full_dosing, by = c("ID", "labdat"))
ID labrec labval labdat dosrec doslev dosdat
1 1 1 4.92 2020-06-17 2 0.1 2020-06-15
2 1 2 2.89 2020-06-24 3 0.1 2020-06-22
3 1 3 14.01 2020-07-08 4 0.9 2020-07-07
4 2 1 3.92 2020-06-06 1 0.2 2020-06-05
5 2 2 17.58 2020-06-26 3 0.3 2020-06-24
但是,它的效率低于 data.table
解决方案,因为您需要先 complete
dosing
数据帧。
解决方案基于此数据:
#' Dosing file
#' ----------------------------------
dosdatID1<-c("2020-06-06", "2020-06-15", "2020-06-22", "2020-07-07", "2020-07-17")
dosdatID2<-c("2020-06-05", "2020-06-08", "2020-06-24", "2020-06-27")
dosing<-data.frame(
ID=c(rep(1, 5), rep(2, 4)),
dosrec=c(1:5, 1:4),
doslev=c(c(0.1, 0.1, 0.1, 0.9, 0.9), c(0.2, 0.2, 0.3, 0.3)),
dosdat=as.Date(c(dosdatID1, dosdatID2)))
#' Lab values file
#' ----------------------------------
labdatID1<-c("2020-06-17", "2020-06-24", "2020-07-08")
labdatID2<-c("2020-06-06", "2020-06-26")
labs<-data.frame(
ID=c(rep(1, 3), rep(2, 2)),
labrec=c(1:3, 1:2),
labval=round(c(rnorm(3, 10, 5), rnorm(2, 15, 5)), 2),
labdat=as.Date(c(labdatID1, labdatID2))
)