dt1 <- data.table(x = c("a", "a", "b", "b", "c"),
y = c("2016-03-01", "2016-05-10", "2016-04-14", "2016-06-25", "2016-01-12"))
x y
1: a 2016-03-01
2: a 2016-05-10
3: b 2016-04-14
4: b 2016-06-25
5: c 2016-01-12
dt2 <- data.table(x = c("a", "b", "b", "a"),
y = c("2016-05-13", "2016-04-16", "2016-06-20", "2016-02-28"),
z = c("1", "1", "2", "3"))
x y z
1: a 2016-05-13 1
2: b 2016-04-16 1
3: b 2016-06-20 2
4: a 2016-02-28 3
close.match <- function(dt1x, dt1y, threshold <= 3){
if(dt1x %in% dt2$x){
if(abs(as.numeric(as.Date(dt1y) - as.Date(dt2[x == dt1x][which.min(abs(as.Date(y) - as.Date(dt1y))),y]))) < threshold){
return(dt2[x == dt1x][which.min(abs(as.Date(y) - as.Date(dt1y))),z])
} else {
"unknown"
}
} else {
"unknown"
}
}
dt1[,z:=dt1[,close.match(x,y),by=1:nrow(dt1)][,V1]]
x y z
1: a 2016-03-01 3
2: a 2016-05-10 1
3: b 2016-04-14 1
4: b 2016-06-25 unknown
5: c 2016-01-12 unknown
想法是每个dt1
有两个事件dt2
和y
,时间戳x
,每个x
可以有多个条目,有不同的时间戳。如果匹配z
的两个事件在3天之内发生,则预期输出是将dt1
列添加到dt2$z
,其值为x
。否则返回“未知”。
上面的代码可以正常运行。但问题是矢量化 - 效率极低。希望找到有关如何以更有效的方式解决此类问题的任何想法。
答案 0 :(得分:4)
如果使用current development version of data.table, v1.9.7,则可以使用新的条件连接功能,如下所示:
# v1.9.7+
dt1[dt2, z := i.z, on=.(x, start<=y, end>=y)]
此步骤是在将y
列转换为Date
并将start
和end
仅添加到dt1
之后。
有FR, #1639直接为on
参数提供表达式,以便完成整个任务,如下所示:
dt1[dt2, z := i.z, on=.(x, y-3<=y, y+3>=y)]
我会看看我是否可以加快速度。
答案 1 :(得分:0)
感谢David Arenburg,我想出的是:
dt1 <- data.table(x = c("a", "a", "b", "b", "c"),
y = c("2016-03-01", "2016-05-10", "2016-04-14", "2016-06-25", "2016-01-12"))
dt2 <- data.table(x = c("a", "b", "b", "a"),
y = c("2016-05-13", "2016-04-16", "2016-06-20", "2016-02-28"),
z = c("1", "1", "2", "3"))
dt1[,y:=as.Date(y)]
dt2[,y:=as.Date(y)]
dt1[,start:=y-3]
dt1[,end:=y+3]
dt2[,start:=y]
dt2[,end:=y]
setkey(dt2, start, end)
dt1 <- foverlaps(dt1, dt2, type="any")
dt1 <- dt1[,.(x = i.x, y = i.y, z)]
dt1[is.na(z),z:="unknown"]
dt1
x y z
1: a 2016-03-01 3
2: a 2016-05-10 1
3: b 2016-04-14 1
4: b 2016-06-25 unknown
5: c 2016-01-12 unknown
编辑:好的,虽然这有效。它有点爆炸&#34;爆炸&#34;在大型数据集上,相当快地达到RAM限制。还需要一些改进。
EDIT2:setkey
应该看起来像setkey(dt2, x, start, end)
。否则,它将只查找数据集之间所有可能的时间间隔重叠,而不指定匹配变量。两个数据集上的条目超过100k,确保它过分了。