更新,使用稍作修改的lukeA代码:
我希望这里的基准测试没有问题...
library(data.table)
library(lubridate)
library(microbenchmark)
size = 99999
create_dt <- function() {
set.seed(2016)
dt <- data.table(
ID = 1:size,
fecha = sample(
seq(ymd('2000/01/01'), ymd('2016/11/16'), by="day"),
size, replace = TRUE)
)
dt[, fecha_fin := fecha + sample(1:3, size, replace = TRUE)]
setkey(dt, fecha, fecha_fin)
set(dt, j = 1L, value = NULL)
dt <- dt[,lapply(.SD, as.POSIXct, tz = "CET"),.SDcols=1:2]
}
dt <- create_dt()
f_mdz <- function() {
dt_2 <- data.table(
fecha = seq(min(dt$fecha), max(dt$fecha_fin), by = '1 day')
)[, fecha_fin := fecha]
as.Date(
foverlaps(dt_2, dt)[is.na(fecha) & is.na(fecha_fin),i.fecha])
}
f_lukeA <- function() {
dt2 <- data.table(
fecha = seq(min(dt$fecha), max(dt$fecha_fin), "1 day")
)[,fecha_fin:=fecha+60*60*24-1]
as.Date(
foverlaps(dt2, dt)[is.na(fecha) & is.na(fecha_fin),i.fecha])
}
microbenchmark(
dt_mdz <- f_mdz(),
dt_lukeA <- f_lukeA(),
times = 100)
identical(dt_mdz, dt_lukeA)
旧答案如下:
一个起点(远非高效,例如在data.table
上进行逐行操作...)用于进一步的调查可能是:
library(data.table)
library(lubridate)
library(magrittr)
dt <- data.table(
ID = c(7510607L, 7510608L, 7557931L),
fecha = ymd(c('2014-02-15', '2014-02-16', '2014-02-11')),
fecha_fin = ymd(c('2014-02-27', '2014-02-27', '2014-02-12'))
)
long_dt <- dt[, .(days = seq(fecha, fecha_fin, by = '1 day')), by = ID]
setdiff(
seq(long_dt[, min(days)], long_dt[, max(days)], by = '1 day'),
long_dt[, sort(unique(days))]
) %>% as.Date(origin = '1970-01-01')
请注意,我已经更改了您的数据,实际上有两天(2014年2月13日和2014年2月14日)没有任何活动。
dt2 <- data.table( fecha = seq(min(dt$fecha), max(dt$fecha_fin), by = '1 day') )[, fecha_fin := fecha]
,稍微提高了一些时间。当然,前提是dt$fecha
已经是日期格式。 - m-dzfindOverlaps
比foverlaps
更快(https://www.r-bloggers.com/comparing-the-execution-time-between-foverlaps-and-findoverlaps/)。您选择`foverlaps`有特定的原因吗? - dalomanGRanges
或GRangesList
对象”是不使用findOverlaps
的好借口。 - m-dzfoverlaps
因为它很方便。可能还有更快的替代方法-请随意添加并对它们进行基准测试。 - lukeA