R - найти ближайший рабочий день (чешский) - PullRequest
1 голос
/ 09 июля 2019

Мне нужно создать функцию, которая будет возвращать следующие ближайшие рабочие дни.На сегодня (2019-07-09) результат будет 2019-07-10, так как завтра не деловой или выходной.В случае, если завтра будет выходной день, результат должен быть 2019-07-11, но в случае, если этот день будет выходным / праздничным днем, результатом должен быть ближайший рабочий день.

Вот список местныхделовые каникулы.Между этими двумя днями в апреле - канун Пасхи, и даты меняются, но я исправлю это самостоятельно в будущем.

business_holidays <- c("01-01", "04-19", "04-22", "05-01", "05-08", "07-05", "07-06", 
    "09-28", "10-28", "11-17", "12-24", "12-25", "12-26")

Вот то, что я создал.

    library(dplyr)
    library(lubridate) 

df <- data.frame(
      date=seq(as.Date("2019-01-01"), as.Date("2019-12-31"), "days")
      ) %>% 
      mutate(
        weekend = if_else(wday(date) %in% c(7, 1), 1, 0),

        business_holiday = if_else(
          format(date, "%m-%d") %in% business_holidays & weekend == 0,
          1, 0),

        next_business_dt = date + 1
      )

next_business_dt неверно, поскольку следующий день может быть выходным (1 или 2 дня), а ближайший понедельник может бытьделовой праздник.Эти деловые каникулы могут длиться даже дольше, чем один день, например, канун Рождества - в 2017 году были выходные, а затем 3 дня в канун Рождества.

1 Ответ

0 голосов
/ 09 июля 2019

Одним из возможных решений является использование функции fill() пакета tidyr.

Сначала заполните столбец next_business_dt с датой, если это рабочий день, и с NA, если день соответствует выходным или праздничным дням:

library(dplyr)
library(lubridate)
library(tidyr)

df <- data.frame(
      date = seq(as.Date("2019-01-01"), as.Date("2019-12-31"), "days")
      ) %>% 
      mutate(
        weekend = if_else(wday(date) %in% c(7, 1), 1, 0),

        business_holiday = if_else(
          format(date, "%m-%d") %in% business_holidays & weekend == 0,
          1, 0),

        next_business_dt = ifelse((weekend | business_holiday),
                NA, format(date, "%Y-%m-%d")
              )

      )

Затем, чтобы заполнить столбец next_business_dt ближайшей следующей датой без NA:

res <- df %>% fill(next_business_dt, .direction = "up")

Работает так:

date weekend business_holiday next_business_dt 1 2019-01-01 0 1 2019-01-02 2 2019-01-02 0 0 2019-01-02 3 2019-01-03 0 0 2019-01-03 4 2019-01-04 0 0 2019-01-04 5 2019-01-05 1 0 2019-01-07 6 2019-01-06 1 0 2019-01-07 7 2019-01-07 0 0 2019-01-07

Хотя, если последний день или дни года не являются рабочими днями (как это имеет место в 2017 году), НС останутся в некоторых последних строках next_business_dt. Это может быть решено, например, если мы расширим последовательность дат до нескольких дней в следующем году, а затем урежем результат.

...