我有两个R表,每个表都有一个用户列表和一个时间戳,对应于他们采取某个操作的时间.
这些(df1
)中的第一个表有一个详尽的用户列表,用户将有多个具有不同时间戳的行.
第二个(df2
)将有一个更有限的用户列表,但用户将再次使用不同的时间戳在表中.
我希望能够做的是加入这两个表,最后得到一个与用户匹配的表和df1
最接近的时间戳df2
,只要时间戳df2
发生在一个表之后df1
.
例如,如果我有两个表,如:
df1 <- data.frame(c(1,1,2,3), as.POSIXct(c('2016-12-01 08:53:20', '2016-12-01 12:45:47', '2016-12-01 15:34:54', '2016-12-01 00:49:50'))) names(df1) <- c('user', 'time') df2 <- data.frame(c(1,1,3), as.POSIXct(c('2016-12-01 07:11:01', '2016- 12-01 11:50:11', '2016-12-01 01:19:10'))) names(df2) <- c('user', 'time')
给我们:
> df1 user time 1 1 2016-12-01 08:53:20 2 1 2016-12-01 12:45:47 3 2 2016-12-01 15:34:54 4 3 2016-12-01 00:49:50 > df2 user time 1 1 2016-12-01 07:11:01 2 1 2016-12-01 11:50:11 3 3 2016-12-01 01:19:10
我希望得到的输出看起来像:
user time_1 time_2 1 2016-12-01 08:53:20 2016-12-01 11:50:11 1 2016-12-01 12:45:47 NA 2 2016-12-01 15:34:54 NA 3 2016-12-01 00:49:50 2016-12-01 01:19:10
我非常坚持让这个联盟得以解决.作为一个额外的复杂层,我喜欢它,如果有一个参数控制时间窗口以允许匹配(即只有df2
在X
几分钟之内才加入行df1
),但实际上这是主要问题的次要因素.
问题的第一部分可以通过sqldf
包来回答.
library(sqldf) df3 <- sqldf("SELECT * FROM df1 a LEFT JOIN df2 b ON a.time < b.time AND a.user = b.user")[,c(1:2, 4)] #rename to match OP post names(df3) <- c("user", "time_1", "time_2") > df3 user time_1 time_2 1 1 2016-12-01 08:53:20 2016-12-01 11:50:11 2 1 2016-12-01 12:45:473 2 2016-12-01 15:34:54 4 3 2016-12-01 00:49:50 2016-12-01 01:19:10
如果您想要一个允许匹配的时间窗口,您可以在SQL
语句中减去秒,如下所示:
df3 <- sqldf("SELECT * FROM df1 a LEFT JOIN df2 b ON a.time < (b.time - 10000) AND a.user = b.user")[,c(1:2, 4)] > df3 user time time.1 1 1 2016-12-01 08:53:20 2016-12-01 11:50:11 2 1 2016-12-01 12:45:473 2 2016-12-01 15:34:54 4 3 2016-12-01 00:49:50
请注意,无论您选择什么,b.time
都将在几秒钟内完成.