1) Base R - sapply Используется база R. Для каждого компонента dt
в data.df
он находит все значения времени и даты, превышающие его в lookup.df
в ту же дату, а затем возвращает Индекс первый. Наконец, он объединяет data.df и строки этих индексов lookup.df
.
ix <- sapply(data.df$dt, function(dt) with(lookup.df,
which(ldt >= dt & as.Date(ldt, tz = "") == as.Date(dt, tz = ""))[1]
))
res <- cbind(data.df, lookup.df[ix, ])
rownames(res) <- NULL
, дающий:
> res
dt v1 ldt lv
1 2020-01-08 11:30:00 1 2020-01-08 11:30:00 2
2 2020-01-10 11:30:00 2 2020-01-10 11:31:00 5
3 2020-01-11 12:30:00 3 <NA> NA
2) База R - объединение Это альтернативный подход базы R. Добавьте столбец даты к каждому фрейму входных данных, а затем объедините их по этому столбцу. Удалите все строки, для которых дата / время lookup.df меньше, чем дата / время data.df, а затем возьмите первую строку каждого набора строк, полученных из той же исходной строки data.df. Это позволит получить совпадения, за исключением того, что пропущены строки, у которых вообще нет совпадений, поэтому выполните второе слияние, чтобы получить их обратно.
data.df$date <- as.Date(data.df$dt, tz = "")
lookup.df$date <- as.Date(lookup.df$ldt, tz = "")
m <- merge(data.df, lookup.df, by = "date", all.x = TRUE, all.y = FALSE)
m <- subset(m, dt <= ldt)
m <- m[!duplicated(m[1:3]), ]
merge(data.df[-3], m[-1], by = c("dt", "v1"), all.x = TRUE, all.y = FALSE)
, что дает:
dt v1 ldt lv
1 2020-01-08 11:30:00 1 2020-01-08 11:30:00 2
2 2020-01-10 11:30:00 2 2020-01-10 11:31:00 5
3 2020-01-11 12:30:00 3 <NA> NA
3) SQL Несмотря на то, что вопрос, заданный для решения с базовым R, здесь дополнительно добавлено решение sql, поскольку оно обеспечивает особенно прямой перевод задачи в код в виде самостоятельного соединения со сложным условием. , Он выполняет левое соединение с указанным условием и принимает минимум ldt
, найденный во всех строках, полученных из одной и той же строки в data.df.
library(sqldf)
data.df$date <- as.Date(data.df$dt, tz = "")
lookup.df$date <- as.Date(lookup.df$ldt, tz = "")
sqldf("select D.dt, D.v1, min(L.ldt) as ldt, L.lv
from [data.df] D left join [lookup.df] L
on D.dt <= L.ldt and D.date == L.date
group by D.rowid")
, давая:
dt v1 ldt lv
1 2020-01-08 11:30:00 1 2020-01-08 11:30:00 2
2 2020-01-10 11:30:00 2 2020-01-10 11:31:00 5
3 2020-01-11 12:30:00 3 <NA> NA
Примечание
В вопросе с причудливыми кавычками была проблема, которую R не может прочитать, поэтому мы использовали это в качестве ввода:
data.df <- data.frame(dt = as.POSIXct(c('2020-01-08 11:30:00',
'2020-01-10 11:30:00', '2020-01-11 12:30:00')),
v1=c(1,2,3))
lookup.df <- data.frame(ldt = as.POSIXct(c('2020-01-08 11:29:00',
'2020-01-08 11:30:00', '2020-01-08 11:31:00', '2020-01-10 10:30:00',
'2020-01-10 11:31:00', '2020-01-11 11:30:00', '2020-01-12 11:30:00')),
lv = 1:7)