Первая половина - это комментарий @ akrun, но он расширен за счет включения предварительных условий. (Если вы вернетесь и ответите, я с радостью предоставлю вам более подробную информацию.) Вторая половина новая (и часто упускается из виду).
data.table
data.table::foverlaps
выполняет соединения на основе перекрытий / неравенств (в отличие от базовых merge
и dplyr::*_join
, которые работают только на строгих равенствах). Одним из предварительных условий для использования overlaps
(в дополнение к классу data.table
) является правильность key
полей времени.
library(data.table)
setDT(times)
setDT(chunks)
# set the keys
setkey(times, start, stop)
setkey(chunks, t1, t2)
# the join
+(!is.na(foverlaps(chunks, times, which = TRUE, mult = 'first')))
# [1] 1 1 1 1 1 0
Функция фактически возвращает, какие строки в каждой строке times
соответствует в chunks
:
foverlaps(chunks, times, which = TRUE, mult = 'first')
# [1] 1 2 2 3 3 NA
sqldf
data.table
- не единственный инструмент R, позволяющий это сделать. Это решение работает с любым вариантом data.frame
(base, data.table
или tbl_df
).
Вот это:
library(sqldf)
sqldf("
select c.t1, c.t2,
(case when drug is null then 0 else 1 end) > 0 as n
from chunks c
left join times t on
(t.start between c.t1 and c.t2) or (t.stop between c.t1 and c.t2)
or (c.t1 between t.start and t.stop) or (c.t2 between t.start and t.stop)
group by c.t1, c.t2")
# t1 t2 n
# 1 0 4 1
# 2 4 8 1
# 3 8 12 1
# 4 12 16 1
# 5 16 20 1
# 6 20 24 0
(я не знаю, возможно ли это чтобы уменьшить logi c этого соединения, а также если оно не будет вести себя неправильно с другими данными.)
Если вам нужно количество наркотиков, которые встречаются в каждом временном интервале, я думаю, вы можете использовать sum(case when ... end) as n
.