【发布时间】:2016-08-24 12:42:01
【问题描述】:
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 可以有多个条目,具有不同的时间戳。如果两个匹配 x 的事件在 3 天内发生,则预期的输出是将列 z 添加到 dt1,其值来自 dt2$z。否则返回“未知”。
上面的代码可以工作并且就是这样做的。但问题是矢量化——它的效率极低。希望找到有关如何以更有效的方式解决此类问题的任何想法。
【问题讨论】:
-
使用
ifelse矢量化? -
你为什么要按行运行
as.Date??而且你每次都做6次?在进行任何计算之前,您应该做的第一件事是dt1[, y := as.IDate(y)] ; dt2[, y := as.IDate(y)]。其次,我会在这里尝试滚动加入 -
可能是两个滚动连接。像
indx1 <- dt2[dt1, on = c(x = "x", y = "y"), roll = -3, which = TRUE] ; indx2 <- dt2[dt1, on = c(x = "x", y = "y"), roll = 3, which = TRUE] ; dt1[!is.na(indx1), z := dt2[na.omit(indx1), z]] ; dt1[!is.na(indx2), z := dt2[na.omit(indx2), z]] ; dt1这样的东西可以给你一些想法。或者试试foverlaps -
固定日期,它可能只产生很小的改进。并感谢有关 dt roll 参数/foverlaps 的指示。我会检查出来的。
标签: r date data.table matching