Альтернатива с findInterval
.
Создание последовательности дат ('tmp'), начиная с основного дня недели ('wd') в неделю min
'даты', до max
'date'.
Выбор дат, соответствующих целевому рабочему дню ('wds').
Выбор рабочих дней из 'date' ('date_1_5').
ИспользованиеfindInterval
для перевода 'wds' к ближайшему доступному рабочему дню в 'date_1_5'.
f <- function(wd, dates){
tmp <- seq(as.Date(paste(format(min(dates), "%Y-%W"), wd, sep = "-"),
format = "%Y-%W-%u"),
max(dates), by = 1)
wds <- tmp[as.integer(format(tmp, "%u")) == wd]
dates_1_5 <- dates[as.integer(format(dates, "%u")) %in% 1:5]
dates_1_5[findInterval(wds, dates_1_5, left.open = TRUE) + 1]
}
Некоторые примеры:
d <- seq.Date(as.Date("2017-11-16"), as.Date("2017-11-24"), by = 1)
dates <- d[d != as.Date("2017-11-23")]
f(wd = 4, dates)
# [1] "2017-11-16" "2017-11-24"
dates <- d[d != as.Date("2017-11-16")]
f(wd = 4, dates)
# [1] "2017-11-17" "2017-11-23"
dates <- d[!(d %in% as.Date(c("2017-11-16", "2017-11-17", "2017-11-21", "2017-11-23")))]
f(wd = 2, dates)
# [1] "2017-11-20" "2017-11-22"
Чуть более компактно при использовании data.table
подвижного соединения:
library(data.table)
wd <- 2
# using 'dates' from above
d1 <- data.table(dates)
d2 <- data.table(dates = seq(as.Date(paste(format(min(dates), "%Y-%W"), wd, sep = "-"),
format = "%Y-%W-%u"),
max(dates), by = 1))
d1[wday(dates) %in% 2:6][d2[wday(dates) == wd + 1],
on = "dates", .(x.dates), roll = -Inf]
...или неэквивалентное объединение:
d1[wday(dates) %in% 2:6][d2[wday(dates) == wd + 1],
on = .(dates >= dates), .(x.dates), mult = "first"]
При желании просто включите функцию, как указано выше.