【发布时间】:2018-01-29 06:37:21
【问题描述】:
在为问题dplyr or data.table to calculate time series aggregations in R 准备answer 时,我注意到我确实得到了不同的结果,具体取决于表是更新到位还是作为新对象返回。此外,当我更改 non-equi join 条件中的列顺序时,我确实得到了不同的结果。
目前,我对此没有任何解释,可能是由于我方面的重大误解或简单的编码错误。
请注意,这个问题特别要求 对观察到的
data.table连接行为的解释。如果你 有潜在问题的替代解决方案,请感觉 免费向original question发布答案。
原始问题和工作答案
最初的问题是如何使用这些数据计算每位患者在住院前 365 天内的住院次数(包括实际住院次数):
library(data.table) # version 1.10.4 (CRAN) or 1.10.5 (devel built 2017-08-19)
DT0 <- data.table(
patient.id = c(1L, 2L, 1L, 1L, 2L, 2L, 2L),
hospitalization.date = as.Date(c("2013/10/15", "2014/10/15", "2015/7/16", "2016/1/7",
"2015/12/20", "2015/12/25", "2016/2/10")))
setorder(DT0, patient.id, hospitalization.date)
DT0
patient.id hospitalization.date 1: 1 2013-10-15 2: 1 2015-07-16 3: 1 2016-01-07 4: 2 2014-10-15 5: 2 2015-12-20 6: 2 2015-12-25 7: 2 2016-02-10
下面的代码给出了预期的答案(为清楚起见,此处添加了额外的帮助列)
# add helper columns
DT0[, start.date := hospitalization.date - 365][
, end.date := hospitalization.date][]
DT0
patient.id hospitalization.date start.date end.date 1: 1 2013-10-15 2012-10-15 2013-10-15 2: 1 2015-07-16 2014-07-16 2015-07-16 3: 1 2016-01-07 2015-01-07 2016-01-07 4: 2 2014-10-15 2013-10-15 2014-10-15 5: 2 2015-12-20 2014-12-20 2015-12-20 6: 2 2015-12-25 2014-12-25 2015-12-25 7: 2 2016-02-10 2015-02-10 2016-02-10
result <- DT0[DT0, on = c("patient.id", "hospitalization.date>=start.date",
"hospitalization.date<=end.date"),
.(hospitalizations.last.year = .N), by = .EACHI][]
result
patient.id hospitalization.date hospitalization.date hospitalizations.last.year 1: 1 2012-10-15 2013-10-15 1 2: 1 2014-07-16 2015-07-16 1 3: 1 2015-01-07 2016-01-07 2 4: 2 2013-10-15 2014-10-15 1 5: 2 2014-12-20 2015-12-20 1 6: 2 2014-12-25 2015-12-25 2 7: 2 2015-02-10 2016-02-10 3
除了重命名和重复的列名(保留原样用于比较)。
对于patient.id == 2,最后一行的结果为 3,因为该患者自 2015-02-10 以来第三次于 2016-02-10 住院。
就地加入更新
result 是一个新的data.table 对象,它占用了额外的内存。我尝试使用以下方法更新原始 data.table 对象:
# use copy of DT0 which can be safely modified
DT <- copy(DT0)
DT[DT, on = c("patient.id", "hospitalization.date>=start.date",
"hospitalization.date<=end.date"),
hospitalizations.last.year := .N, by = .EACHI]
DT
patient.id hospitalization.date start.date end.date hospitalizations.last.year 1: 1 2013-10-15 2012-10-15 2013-10-15 1 2: 1 2015-07-16 2014-07-16 2015-07-16 2 3: 1 2016-01-07 2015-01-07 2016-01-07 2 4: 2 2014-10-15 2013-10-15 2014-10-15 1 5: 2 2015-12-20 2014-12-20 2015-12-20 3 6: 2 2015-12-25 2014-12-25 2015-12-25 3 7: 2 2016-02-10 2015-02-10 2016-02-10 3
DT 现已更新就地,但第 5 行和第 6 行现在分别显示 3 次住院,而不是 1 或 2 次。现在似乎为每一行返回了上一时期内的住院总数。
更改条件中列的顺序。
非等值连接条件中的列顺序也很重要,即使在自连接中也是如此:
result <- DT0[DT0, on = c("patient.id", "start.date<=hospitalization.date",
"end.date>=hospitalization.date"),
.(hospitalizations.last.year = .N), by = .EACHI][]
result
我的期望是 "start.date<=hospitalization.date" 将等同于 "hospitalization.date>=start.date"(请注意,< 和 > 也已切换)但结果
patient.id start.date end.date hospitalizations.last.year 1: 1 2013-10-15 2013-10-15 1 2: 1 2015-07-16 2015-07-16 2 3: 1 2016-01-07 2016-01-07 1 4: 2 2014-10-15 2014-10-15 1 5: 2 2015-12-20 2015-12-20 3 6: 2 2015-12-25 2015-12-25 2 7: 2 2016-02-10 2016-02-10 1
不同。看来现在正在统计即将住院的人数
有趣的是,更新就地现在确实返回了相同的结果(除了一些列名):
# use copy of DT0 which can be safely modified
DT <- copy(DT0)
DT[DT, on = c("patient.id", "start.date<=hospitalization.date",
"end.date>=hospitalization.date"),
hospitalizations.last.year := .N, by = .EACHI]
DT
patient.id hospitalization.date start.date end.date hospitalizations.last.year 1: 1 2013-10-15 2012-10-15 2013-10-15 1 2: 1 2015-07-16 2014-07-16 2015-07-16 2 3: 1 2016-01-07 2015-01-07 2016-01-07 1 4: 2 2014-10-15 2013-10-15 2014-10-15 1 5: 2 2015-12-20 2014-12-20 2015-12-20 3 6: 2 2015-12-25 2014-12-25 2015-12-25 2 7: 2 2016-02-10 2015-02-10 2016-02-10 1
相关
有一个潜在的related question 导致issue reported on github。
有一个answer by Arun 与x. 前缀的使用有关非等连接。
【问题讨论】:
标签: r join data.table self-join