我有两个数据框,一个是住院,另一个是实验室结果。我需要确定实验结果发生在哪家医院,并将入院和出院日期从医院数据框复制到相关实验室结果的行中。
我正在使用for循环来遍历实验室结果,然后使用在医院记录中查找匹配条目(通过患者SSN和周围日期)的语句和子集。
这是一个非常大的数据集,使用for循环非常慢。有没有办法加速这种问题? (我有几个类似的问题,所以会喜欢答案。)
添加了样本数据,请注意每位患者有多个医院记录,目标是从日期与实验日期重叠的记录中获取日期。在此示例中,结果数据框应仅具有患者1的入院和出院日期,因为患者2没有医院数据,患者3的记录与实验日期不重叠。
testDate <- as.Date(c("2017-01-15", "2017-01-15", "2017-01-15"))
patientSSN <- c("1","2","3")
labs <- data.frame(patientSSN, testDate)
# patientSSN testDate
# 1 1 2017-01-15
# 2 2 2017-01-15
# 3 3 2017-01-15
patientSSN <- c("1","1","3","3")
admissionDate <- as.Date(c("2017-01-07", "2017-02-01", "2016-12-01", "2017-01-16"))
dischargeDate <- as.Date(c("2017-01-16", "2017-02-10", "2016-12-15", "2017-02-01"))
hospitalRec <- data.frame(patientSSN, admissionDate, dischargeDate)
for (I in 1:nrow(labs)) {
labs[I,]$admissionDate <- hospitalRec[hospitalRec$patientSSN == labs[I,]$patientSSN & hospitalRec$admissionDate <= labs[I,]$testDate & hospitalRec$dischargeDate >= labs[I,]$testDate,]$admissionDate
labs[I,]$admissionDate <- hospitalRec[hospitalRec$PatientSSN == labs[I,]$PatientSSN & hospitalRec$admissionDate <= labs[I,]$testDate & hospitalRec$dischargeDate >= labs[I,]$testDate,]$dischargeDate
}
所需的数据框如下所示:
labs:
patientSSN testDate admissionDate dischargeDate
1 2017-01-15 2017-01-07 2017-01-16
2 2017-01-15 NA NA
3 2017-01-15 NA NA
请注意,在实际数据中,还存在多个医院记录符合条件(部门之间的排放)的问题,这些记录具有相同的入院日期,但不同的出院时间与最新的记录是重要的。但首先要做的事情......
答案 0 :(得分:1)
非equi连接有效,例如data.table:
library(data.table)
setDT(labs); setDT(hospitalRec)
labs[hospitalRec, on=.(patientSSN, testDate >= admissionDate, testDate <= dischargeDate),
`:=`(aDate = i.admissionDate, dDate = i.dischargeDate)]
patientSSN testDate aDate dDate
1: 1 2017-01-15 2017-01-07 2017-01-16
2: 2 2017-01-15 <NA> <NA>
3: 3 2017-01-15 <NA> <NA>
在实际数据中,还存在多个医院记录符合条件(部门之间的排放)的问题,这些记录将具有相同的入院日期,但不同的出院时间与最新的记录是重要的。
如果hospitalRec
已排序,则上面添加mult="last"
应该有效。有关完整文档,请参阅?data.table
。或者,您可以创建一个排除这些“重复”的医院记录版本,例如......排序然后
lastRec = unique(hospitalRec, by=c("patientSSN", "admissionDate"), fromLast=TRUE))
setorder
函数是对data.tables进行排序的标准工具。
答案 1 :(得分:0)
假设这与您的df看起来类似,请使用dplyr::left_join
:
hospital_data <- data.frame(PatientSSN = c('1234567890','9876543210'),
admit = c('8/1/17','8/5/17'),
discharge = c('8/10/17','8/15/17'))
lab_data <- data.frame(specimen_id = c('foo1','foo2','foo3','foo4','foo5','foo6','foo7'),
PatientSSN = c('1234567890','1234567890','1234567890','9876543210','9876543210','9876543210','8527419600'),
test = c('hemoglobin','inr','platelette','hemoglobin','inr','platelette','inr'))
lab_data %>% left_join(hospital_data)
specimen_id PatientSSN test admit discharge
1 foo1 1234567890 hemoglobin 8/1/17 8/10/17
2 foo2 1234567890 inr 8/1/17 8/10/17
3 foo3 1234567890 platelette 8/1/17 8/10/17
4 foo4 9876543210 hemoglobin 8/5/17 8/15/17
5 foo5 9876543210 inr 8/5/17 8/15/17
6 foo6 9876543210 platelette 8/5/17 8/15/17
7 foo7 8527419600 inr <NA> <NA>
请注意,您的id变量(PatientSSN)
在每个表中都是相同的。
答案 2 :(得分:0)
好的 - 这是一种方法。但是,快速抬头;您不太可能使用没有特定于访问/帐户的ID变量的EMR数据。在使用SSN之前,我希望将其用作唯一标识符。尽管如此;这应该工作。我使用了您上面提供的数据。
for(i in 1:nrow(labs)){
#finding the ID (ssn)
ssn_match_df <- hospitalRec[which(as.character(labs$patientSSN[i]) == as.character(hospitalRec$patientSSN)),]
#finding record in table where the test date fall between the admit/discharge
ssn_match_df <- ssn_match_df[which(labs$testDate[i] >= ssn_match_df$admissionDate &
labs$testDate[i] <= ssn_match_df$dischargeDate),]
if(nrow(ssn_match_df)>0){
labs[i,3] <- as.character(ssn_match_df[1,2])
labs[i,4] <- as.character(ssn_match_df[1,3])
} else {
labs[i,3] <- NA
labs[i,4] <- NA
}
}
colnames(labs)[3] <- 'admitDate'
colnames(labs)[4] <- 'dischargeDate'