这可能非常复杂,我怀疑需要先进的知识。我现在有两种不同类型的data.frames需要合并:
数据:
Dataframe A:
按患者ID列出所有输血日期。每次输血都由一个单独的行代表,患者可以进行多次输血。不同的患者可以在同一天进行输血。
Patient ID Transfusion.Date
1 01/01/2000
1 01/30/2000
2 04/01/2003
3 04/01/2003
B类数据框包含其他日期的测试结果,也包括患者ID:
Patient ID Test.Date Test.Value
1 11/30/1999 negative
1 01/15/2000 700 copies/uL
1 01/27/2000 900 copies/uL
2 03/30/2003 negative
我想要的是具有相同行数的Dataframe A(每次输入为1),并将最新的Test.Value作为单独的列。每个输血日期应该具有与输血最密切(之前)进行的测试的测试结果。
期望的输出:
- >
Patient ID Transfusion.Date Pre.Transfusion.Test
1 01/01/2000 negative
1 01/30/2000 900 copies/ul
2 04/01/2003 negative
3 04/01/2003 NA
我认为一般策略是按患者ID对data.frames进行子集化。然后获取患者1的所有输血日期,检查哪个结果最接近每个元素的所有可用test_dates,然后返回最接近的值。
如何解释R来做到这一点?
编辑1 :以下是这些示例的R代码
df_A <- data.frame(MRN = c(1,1,2,3),
Transfusion.Date = as.Date(c('01/01/2000', '01/30/2000',
'04/01/2003','04/01/2003'),'%m/%d/%Y'))
df_B <- data.frame(MRN = c(1,1,1,2),
Test.Date = as.Date(c('11/30/1999', '01/15/2000', '01/27/2000',
'03/30/2003'),'%m/%d/%Y'), Test.Result = c('negative',
'700 copies/ul','900 copies/ul','negative'))
编辑2:
为了澄清,结果数据应为:患者A在第X天和第Y天接受输血(对于df_A)。在第X天输血之前,他最近的测试结果是X(最接近第一次输血的测试日期,在df_B中)。在第Y天输血之前,他最近的测试结果是Y(第二次输血之前,也是df_B。df_B还包含一堆其他测试日期,最终输出不需要。
答案 0 :(得分:5)
在这里使用data.table
的滚动连接:
require(data.table)
setkey(setDT(df_A), MRN, Transfusion.Date)
setkey(setDT(df_B), MRN, Test.Date)
df_B[df_A, roll=TRUE]
# MRN Test.Date Test.Result
# 1: 1 2000-01-01 negative
# 2: 1 2000-01-30 900 copies/ul
# 3: 2 2003-04-01 negative
# 4: 3 2003-04-01 NA
setDT
通过引用将data.frame
转换为data.table
(无需任何额外复制)。这会导致df_A
和df_B
现在成为data.tables。
setkey
按我们提供的列对data.table
进行排序,并将标记这些列作为关键列,这样我们就可以使用二进制搜索< / em>基于联接。
我们在关键列上执行x[i]
表单的连接,i
的每一行,x
的匹配行(如果有的话,其他NA)与i
的行一起返回。这就是我们所说的 equi-join 。通过添加roll = TRUE
,如果不匹配,最后一次观察将继续进行(LOCF)。这就是我们所说的滚动连接。按升序排序(由于setkey()
)确保最后一次观察是最近的日期。
HTH
答案 1 :(得分:0)
dfLast <- df_B[ df_B$Test.Date %in%
as.Date( tapply(df_B$Test.Date, df_B$MRN, tail,1),"1970-01-01"), ]
merge(df_A, dfLast, by=c(1:2,1:2) ,all.y=TRUE)
MRN Transfusion.Date Test.Result
1 1 2000-01-27 900 copies/ul
2 2 2003-03-30 negative
编辑。有一些逻辑错误和一些sytactic错误。 tapply返回日期的整数值,正如您所指出的那样,我在数据缩减步骤中使用了错误的列名。
答案 2 :(得分:0)
好的,谢谢大家的帮助。我花了很多辛劳,血,汗和眼泪,但这是我提出的解决方案:
df_AB&lt; - merge(df_A,df_B,all.x = T)
df_AB:
MRN Transfusion.Date Test.Date Test.Result
1 1 2000-01-01 1999-11-30 negative
2 1 2000-01-01 2000-01-15 700 copies/ul
3 1 2000-01-01 2000-01-27 900 copies/ul
4 1 2000-01-30 1999-11-30 negative
5 1 2000-01-30 2000-01-15 700 copies/ul
6 1 2000-01-30 2000-01-27 900 copies/ul
7 2 2003-04-01 2003-03-30 negative
8 3 2003-04-01 <NA> <NA>
使用dplyr
df_tests <- df_AB %>%
group_by(MRN, Transfusion.Date) %>%
mutate(Time.Difference = Transfusion.Date - Test.Date) %>%
filter(Time.Difference > 0) %>%
arrange(Time.Difference) %>%
summarize(Test.Date = Test.Date[1], Test.Result = Test.Result[1])
df_tests:
MRN Transfusion.Date Test.Date Test.Result
1 1 2000-01-01 1999-11-30 negative
2 1 2000-01-30 1999-11-30 negative
3 2 2003-04-01 2003-03-30 negative
using merge again for MRN3:
df_desired <- merge(df_A, df_tests, all.x = T)
MRN Transfusion.Date Test.Date Test.Result
1 1 2000-01-01 1999-11-30 negative
2 1 2000-01-30 2000-01-27 900 copies/ul
3 2 2003-04-01 2003-03-30 negative
4 3 2003-04-01 <NA> <NA>