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
Idee ist, dass es zwei Ereignisse dt1
und dt2
mit Zeitstempel y
für jeden x
, kann es für jeden x
, mit unterschiedlichen Zeitstempeln mehr als ein Eintrag sein. Die erwartete Ausgabe besteht darin, die Spalte z
zu dt1
mit einem Wert von dt2$z
hinzuzufügen, wenn zwei Ereignisse für die Übereinstimmung x
innerhalb von 3 Tagen aufeinander folgen. Andernfalls "unbekannt" zurückgeben.R: Matching am nächsten Tag (Effizienz Ausgabe)
Der obige Code funktioniert und macht genau das. Aber das Problem ist die Vektorisierung - es ist extrem ineffizient. In der Hoffnung, irgendwelche Ideen zu finden, wie man diese Art von Problemen auf effizientere Weise lösen kann.
Verwenden Sie 'ifelse', um zu vektorisieren? – aichao
Warum läuft 'asDate' by row ?? Und du machst es jedes Mal 6 Mal? Das erste, was Sie tun sollten, ist 'dt1 [, y: = as.IDate (y)]; dt2 [, y: = as.IDate (y)] 'vor jeder Berechnung. Zweitens würde ich hier einen rollenden Join versuchen –
Vielleicht zwei rollende Joins. Etwas wie 'indx1 <- dt2 [dt1, ein = c (x =" x ", y =" y "), roll = -3, was = WAHR]; indx2 <- dt2 [dt1, ein = c (x = "x", y = "y"), Rolle = 3, was = WAHR]; dt1 [! is.na (indx1), z: = dt2 [na.mit (indx1), z]]; dt1 [! is.na (indx2), z: = dt2 [na.mit (indx2), z]]; dt1' könnte dir ein paar Ideen geben. Oder vielleicht versuchen Sie 'foverlaps' –