R dplyr | Разделите дни месяца на четыре категории: Пн, будни, Пт, выходные

#r #function #date #dplyr #timestamp

Вопрос:

Я работаю над фреймом данных временных меток. Выдержка из переменных, связанных с датой, из январского образца фрейма данных:

 sample_dates <- data.frame(date = c("2021-01-01", "2021-01-02", "2021-01-03", "2021-01-04", "2021-01-05", "2021-01-06", "2021-01-07", "2021-01-08", "2021-01-09", "2021-01-10", "2021-01-11", "2021-01-12", "2021-01-13", "2021-01-14", "2021-01-15", "2021-01-16", "2021-01-17", "2021-01-18", "2021-01-19", "2021-01-20", "2021-01-21", "2021-01-22", "2021-01-23", "2021-01-24", "2021-01-25", "2021-01-26", "2021-01-27", "2021-01-28", "2021-01-29", "2021-01-30", "2021-01-31"))

sample_dates <- sample_dates %>% 
    mutate(date = as.POSIXct(date)) %>% 
    mutate(day = factor(format(date, "%a")))
 

Я хочу добавить новую факторную переменную day_cat , псевдокод для которой может быть примерно таким:

 sample_dates <- sample_dates %>% 
    # the month could start on any day and this function should identify it
    # for the sample, I know January 2021 started on Friday
    
    mutate(day_cat = while(month is not over)
        
        if(day == "Fri") {"Fri1"},
        else if(day == "Sat" | day == "Sun") {"Weekend1"},
        else if(day == "Mon") {"Mon1"},
        else if(day == "Tue" | day == "Wed" | day == "Thu") {"Weekdays1"},
        
        # now we're onto the next Friday of the month
        else if(day == "Fri") {"Fri2"},
        else if(day == "Sat" | day == "Sun") {"Weekend2"},
        else if(day == "Mon") {"Mon2"},
        else if(day == "Tue" | day == "Wed" | day == "Thu") {"Weekdays2"},
        ...
        ...
        
        # reached the end of month
        )

    mutate(day_cat = factor(day_cat, levels = c("Mon", "Weekdays", "Fri", "Weekend")))
 

Итак, факторы: Пн = {Пн}; Будни = {Вт, Ср, Чт}; Пт = {Пт}; Выходные = {Сб, Вс}. И я хочу пронумеровать эти факторы как Mon1, Будни1, Пятница 1, Выходные 1, Понедельник 2, Будни2, Пятница 1, Выходные 2, Понедельник 3 и так далее в day_cat переменной (скажем, если месяц начался с понедельника).

Уровни day_cat переменной должны находиться в одном и том же порядке (для целей построения графика).

Если месяц начинается в среду, day_cat то в качестве «Будних дней»будут приниматься только эта среда и четверг (следующий день) 1. Если месяц заканчивается в субботу, day_cat я буду считать только эту субботу «Выходным днем 4» или «Выходным днем 5», в зависимости от того, что это может быть.

Ответ №1:

Здесь day_cat это фактор в хронологическом порядке, хотя, как указано, значения трех дней недели и двух выходных дней будут иметь одинаковый уровень фактора каждую неделю. Это то, чего ты хочешь?

 library(dplyr); library(lubridate)
sample_dates %>%
  mutate(day = wday(date, label = TRUE),
         group = case_when(day == "Mon" ~ "Mon",
                           day == "Fri" ~ "Fri",
                           day %in% c("Sat", "Sun") ~ "Weekend",
                           TRUE ~ "Weekday"),
         weeknum = (day(date)-1) %/% 7   1,
         day_cat = paste0(group, weeknum) %>% fct_inorder()) 
 

Результат

          date day   group weeknum  day_cat
1  2021-01-01 Fri     Fri       1     Fri1
2  2021-01-02 Sat Weekend       1 Weekend1
3  2021-01-03 Sun Weekend       1 Weekend1
4  2021-01-04 Mon     Mon       1     Mon1
5  2021-01-05 Tue Weekday       1 Weekday1
6  2021-01-06 Wed Weekday       1 Weekday1
7  2021-01-07 Thu Weekday       1 Weekday1
8  2021-01-08 Fri     Fri       2     Fri2
9  2021-01-09 Sat Weekend       2 Weekend2
10 2021-01-10 Sun Weekend       2 Weekend2
11 2021-01-11 Mon     Mon       2     Mon2
12 2021-01-12 Tue Weekday       2 Weekday2
13 2021-01-13 Wed Weekday       2 Weekday2
14 2021-01-14 Thu Weekday       2 Weekday2
15 2021-01-15 Fri     Fri       3     Fri3
16 2021-01-16 Sat Weekend       3 Weekend3
17 2021-01-17 Sun Weekend       3 Weekend3
18 2021-01-18 Mon     Mon       3     Mon3
19 2021-01-19 Tue Weekday       3 Weekday3
20 2021-01-20 Wed Weekday       3 Weekday3
21 2021-01-21 Thu Weekday       3 Weekday3
22 2021-01-22 Fri     Fri       4     Fri4
23 2021-01-23 Sat Weekend       4 Weekend4
24 2021-01-24 Sun Weekend       4 Weekend4
25 2021-01-25 Mon     Mon       4     Mon4
26 2021-01-26 Tue Weekday       4 Weekday4
27 2021-01-27 Wed Weekday       4 Weekday4
28 2021-01-28 Thu Weekday       4 Weekday4
29 2021-01-29 Fri     Fri       5     Fri5
30 2021-01-30 Sat Weekend       5 Weekend5
31 2021-01-31 Sun Weekend       5 Weekend5
 

Комментарии:

1. Есть 18 уровней, как я и хотел. Эквивалентная альтернатива для weeknum, однако, похоже, не работает с полом; она дает weeknum как 2 для первого четверга.