提高链接来自两个数据帧的数据的效率

Posted

技术标签:

【中文标题】提高链接来自两个数据帧的数据的效率【英文标题】:Improve efficiency linking data from two data frames 【发布时间】:2017-08-16 17:58:31 【问题描述】:

我有两个数据框,一个是住院时间,另一个是实验室结果。我需要确定实验室结果发生在哪个医院,并将医院数据框中的入院和出院日期复制到相关实验室结果的行中。

我使用 for 循环来遍历实验室结果,然后在医院记录中查找匹配条目(按患者 SSN 和周围日期)的 if 语句和子集。

这是一个相当大的数据集,使用 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

注意,在真实数据中,还存在多个医院记录合格(部门之间的出院)的问题,这些记录的入院日期相同,但出院时间不同,最重要的是最新的出院时间。但首先要做的就是……

【问题讨论】:

能否请您显示示例数据,以及预期的输出?它将帮助其他人正确地帮助您。 尝试使用dplyrjoin 函数合并两个数据帧。如果您重现示例数据,我们可以提供帮助。 提供的样本数据。合并不起作用,因为它无法识别日期问题。 【参考方案1】:

非等值连接有效,例如使用 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 的标准工具。

【讨论】:

【参考方案2】:

假设这与您的 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) 在每个表中都是相同的。

【讨论】:

这忽略了日期问题。实验室结果也有日期,唯一应该选择的入院和出院日期是实验室日期周围的日期。一个简单的合并不会这样做(据我所知)【参考方案3】:

好的,这是一种方法。不过,只是快速提醒一下;您几乎不可能使用没有特定于访问/帐户的 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'

【讨论】:

所以这将快两倍,因为它只扫描一次住院数据帧? 感谢您指出这一点。没有办法绕过我看到的 for 循环。至于 SSN,当您想在多个设施中匹配患者时,最好不要使用每个设施的内部标识符。

以上是关于提高链接来自两个数据帧的数据的效率的主要内容,如果未能解决你的问题,请参考以下文章

来自两个数据帧的总数据按行名匹配

Pandas - 匹配来自两个数据帧的两列并在 df1 中创建新列

来自seaborn facetgrid中不同数据帧的两行

根据来自其他数据帧的位置条件在数据帧上编写选择查询,scala

R:从一个数据帧中提取行,基于列名匹配来自另一个数据帧的值

R中两个数据帧的条件连接