Я пытаюсь рассчитать количество перекрывающихся дней между двумя периодами времени. Один период фиксируется в начальной и конечной датах, другой записывается как начальная и конечная даты во фрейме данных.
Изменить: Я имею дело с объявлениями, которые имеют дату публикации (df $ start) и дату отмены публикации (df $ end). Я пытаюсь выяснить, сколько дней они были в сети в определенном месяце (my.start = 2018-01-01, my.end = 2018-08-31).
library(dplyr)
library(lubridate)
my.start <- ymd("2018-08-01")
my.end <- ymd("2018-08-31")
df <- data.frame(start = c("2018-07-15", "2018-07-20", "2018-08-15", "2018-08-20", "2018-09-01"),
end = c("2018-07-20", "2018-08-05", "2018-08-19", "2018-09-15", "2018-09-15"))
# strings to dates
df <- mutate(df, start = ymd(start), end = ymd(end))
# does not work - calculate overlap in days
df <- mutate(df, overlap = intersect(interval(my.start, my.end), interval(start, end)))
Результаты должны быть 0, 5, 4, 12, 0 дней:
my.start |-------------------------------| my.end
|-----| (0)
|---------| (5)
|----| (4)
|------------------| (12)
|---------------| (0)
В Excel я бы использовал
=MAX(MIN(my.end, end) - MAX(my.start, start) + 1, 0)
но это тоже не работает:
# does not work - calculate via min/max
df <- mutate(df, overlap = max(min(my.end, end) - max(my.start, start) + 1, 0))
Прежде чем я попытаюсь использовать подход Excel с использованием as.numeric()
в отношении дат, я подумал, есть ли более разумный способ сделать это.
РЕДАКТИРОВАТЬ: На самом деле, числовой подход Excel также не похоже на две работы (все результаты равны нулю):
# does not work - calculate via numeric
ms.num <- as.numeric(my.start)
me.num <- as.numeric(my.end)
df <- df %>%
mutate(s.num = as.numeric(start),
e.num = as.numeric(end),
overlap = max(min(e.num, me.num) - max(s.num, ms.num) + 1, 0))
Edit: подход @akrun, кажется, работает для дат ymd. Тем не менее, похоже, что он не работает для ymd_hms раз:
library(dplyr)
library(lubridate)
library(purrr)
my.start <- ymd("2018-08-01")
my.end <- ymd("2018-08-31")
df <- data.frame(start = c("2018-07-15 10:00:00", "2018-07-20 10:00:00", "2018-08-15 10:00:00", "2018-08-20 10:00:00", "2018-09-01 10:00:00"),
end = c("2018-07-20 10:00:00", "2018-08-05 10:00:00", "2018-08-19 10:00:00", "2018-09-15 10:00:00", "2018-09-15 10:00:00"))
# strings to dates
df <- mutate(df, start = ymd_hms(start), end = ymd_hms(end))
# leads to 0 results
df %>% mutate(overlap = map2(start, end, ~ sum(seq(.x, .y, by = '1 day') %in% seq(my.start, my.end, by = '1 day'))))