Как создать интервалы времени начала и окончания с указанными c условиями, когда более одного начала и конца в день и ночь - PullRequest
0 голосов
/ 06 марта 2020

У меня есть дата-кадр с рабочим временем каждого дня недели. У меня есть время начала и окончания каждого дня. Проблема возникает, когда работник дважды работал в один и тот же день. Например, он начал работать в пятницу в 22:00 и закончил в субботу в 8:00, но снова начал работать в 22:00 в субботу вечером. Мой набор данных теперь структурирован так:

enter image description here

dput(droplevels(head(data1, 10)))
structure(list(Mon.Start1 = structure(c(2L, 1L, 1L, 4L, 1L, 3L, 
2L, 4L, 1L, 1L), .Label = c(" ", "14:30:00", "22:30:00", "7:00:00"
), class = "factor"), Mon.End1 = structure(c(4L, 1L, 1L, 2L, 
1L, 6L, 5L, 3L, 1L, 1L), .Label = c(" ", "16:00:00", "17:30:00", 
"23:15:00", "23:30:00", "24:00:00"), class = "factor"), Mon.Start2 = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = " ", class = "factor"), 
    Mon.End2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L), .Label = " ", class = "factor"), Tue.Start1 = structure(c(4L, 
    1L, 3L, 5L, 1L, 2L, 1L, 5L, 5L, 1L), .Label = c(" ", "0:00:00", 
    "14:00:00", "14:30:00", "7:00:00"), class = "factor"), Tue.End1 = structure(c(3L, 
    1L, 4L, 2L, 1L, 5L, 1L, 2L, 2L, 1L), .Label = c(" ", "16:30:00", 
    "23:15:00", "24:00:00", "8:00:00"), class = "factor"), Tue.Start2 = structure(c(1L, 
    1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L), .Label = c(" ", "22:30:00"
    ), class = "factor"), Tue.End2 = structure(c(1L, 1L, 1L, 
    1L, 1L, 2L, 1L, 1L, 1L, 1L), .Label = c(" ", "24:00:00"), class = "factor"), 
    Wed.Start1 = structure(c(1L, 3L, 1L, 3L, 1L, 2L, 1L, 3L, 
    3L, 1L), .Label = c(" ", "0:00:00", "7:00:00"), class = "factor"), 
    Wed.End1 = structure(c(1L, 3L, 1L, 3L, 1L, 5L, 1L, 4L, 2L, 
    1L), .Label = c(" ", "16:30:00", "17:00:00", "17:30:00", 
    "8:00:00"), class = "factor"), Wed.Start2 = structure(c(1L, 
    1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L), .Label = c(" ", "22:30:00"
    ), class = "factor"), Wed.End2 = structure(c(1L, 1L, 1L, 
    1L, 1L, 2L, 1L, 1L, 1L, 1L), .Label = c(" ", "24:00:00"), class = "factor"), 
    Thu.Start1 = structure(c(1L, 1L, 1L, 4L, 1L, 2L, 3L, 4L, 
    4L, 1L), .Label = c(" ", "0:00:00", "14:30:00", "7:00:00"
    ), class = "factor"), Thu.End1 = structure(c(1L, 1L, 1L, 
    2L, 1L, 4L, 3L, 2L, 2L, 1L), .Label = c(" ", "16:30:00", 
    "24:00:00", "8:00:00"), class = "factor"), Thu.Start2 = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = " ", class = "factor"), 
    Thu.End2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L), .Label = " ", class = "factor"), Fri.Start1 = structure(c(2L, 
    1L, 1L, 4L, 3L, 1L, 1L, 4L, 4L, 1L), .Label = c(" ", "6:30:00", 
    "6:45:00", "7:00:00"), class = "factor"), Fri.End1 = structure(c(5L, 
    1L, 1L, 3L, 2L, 1L, 1L, 4L, 2L, 1L), .Label = c(" ", "16:30:00", 
    "16:45:00", "17:30:00", "18:30:00"), class = "factor"), Fri.Start2 = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = " ", class = "factor"), 
    Fri.End2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L), .Label = " ", class = "factor"), Sa.Start1 = structure(c(4L, 
    5L, 1L, 1L, 3L, 1L, 1L, 5L, 1L, 2L), .Label = c(" ", "14:00:00", 
    "14:45:00", "6:30:00", "7:00:00"), class = "factor"), Sa.End1 = structure(c(4L, 
    3L, 1L, 1L, 5L, 1L, 1L, 2L, 1L, 6L), .Label = c(" ", "16:30:00", 
    "17:00:00", "18:30:00", "23:15:00", "24:00:00"), class = "factor"), 
    Sa.Start2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L), .Label = " ", class = "factor"), Sa.End2 = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = " ", class = "factor"), 
    Sun.Start1 = structure(c(4L, 1L, 1L, 1L, 3L, 1L, 1L, 1L, 
    1L, 2L), .Label = c(" ", "0:00:00", "14:45:00", "6:30:00"
    ), class = "factor"), Sun.End1 = structure(c(3L, 1L, 1L, 
    1L, 4L, 1L, 1L, 1L, 1L, 2L), .Label = c(" ", "0:30:00", "16:45:00", 
    "23:15:00"), class = "factor"), Sun.Start2 = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c(" ", "14:00:00"
    ), class = "factor"), Sun.End2 = structure(c(1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c(" ", "24:00:00"), class = "factor")), row.names = c("21", 
"22", "23", "25", "26", "27", "28", "31", "34", "35"), class = "data.frame") 

Я попытался установить время начала и окончания с помощью lubridate пакета. Я также добавил даты в все дни (как .POSICxt) Когда сотрудник работает только один раз в день, он работает, но не тогда, когда он работал дважды. Поскольку иногда мое Конечное время действительно является Конечным временем (поскольку для понедельника 24:00 является конечным временем), но иногда оно продолжается в течение ночи (как пятница и суббота), и поэтому 24:00 не является конечным временем. Есть ли функция, чтобы установить, что каждый раз, когда время запуска равно 00, время начала должно быть start2 с предыдущего дня? Или как я мог решить эту проблему? Цель состоит в том, чтобы создавать перерывы и обозначать каждую смену по времени начала, как ночь, поздняя смена и c, а также время перехода. Также для тех, кто работал дважды, если я сократил и обозначил начальные часы, чтобы определить смену, поскольку у сотрудников есть два начальных часа, я заканчиваю еще одну смену в неделю, что на самом деле не правильно.

Желаемый вывод будет иметь день недели в одном столбце, время начала, время окончания, продолжительность смены, тип смены (выкл., Утреннее, позднее, ночное время), а затем после того, как будет иметь это для каждого дня быть в состоянии сделать некоторые вычисления на недельном уровне и далее на месячном уровне.

Если бы кто-нибудь мог дать мне несколько советов, я был бы очень благодарен. Спасибо

1 Ответ

0 голосов
/ 07 марта 2020

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

Сначала я бы использовал pivot_longer, чтобы поместить в форму, которая имеет смысл оценивать, основываясь на дне, событии. (начало или конец) и номер смены. Также было бы полезно иметь столбец для номера дня, поскольку даты недоступны.

Кажется, что есть пробелы - они были сделаны NA.

Время было преобразовано в секунды с lubridate function hms.

Затем это было возвращено в широкий формат, и были добавлены дополнительные столбцы для обозначения времени после полуночи, которое было включено в день (если значение start для даты было 0). Кроме того, был создан другой столбец, чтобы указать, перешел ли день к полуночи (в этом случае любое последующее время после полуночи будет добавлено для корректировки позже).

Затем для каждого дня будет суммироваться общее время, отработанное в течение дня, а затем рассчитайте скорректированное время на основе того, что вы просили, - это время, прошедшее после полуночи предыдущего дня, если предыдущий день шел до полуночи.

Надеюсь, это полезно.

library(tidyverse)
library(lubridate)

data1 %>%
  pivot_longer(everything(), names_to = c("day", "event", "num"), values_to = "time", names_pattern = "(\\w+).(Start|End)(\\d)") %>%
  mutate(daynum = cumsum(day != lag(day, default = first(day))) + 1) %>%
  na_if(" ") %>%
  mutate(time = as.numeric(hms(time, quiet = TRUE))) %>%
  pivot_wider(id_cols = c(daynum, num, day), names_from = event, values_from = time) %>%
  mutate(PastMN = if_else(Start == 0, End - Start, 0),
         UpToMN = if_else(End == 86400, TRUE, FALSE)) %>%
  group_by(daynum) %>%
  summarise(DayTotal = sum(End - Start, na.rm = TRUE),
            PastMNTotal = sum(PastMN, na.rm = TRUE),
            AnyUpToMN = any(UpToMN, na.rm = T)) %>%
  mutate(DayTotalAdjusted = if_else(lead(PastMNTotal, default = 0) > 0, DayTotal + lead(PastMNTotal), DayTotal),
         DayTotalAdjusted = if_else(lag(AnyUpToMN, default = FALSE) == TRUE, DayTotalAdjusted - PastMNTotal, DayTotalAdjusted)) %>%
  mutate(ShiftLength = DayTotalAdjusted / 3600) %>%
  dplyr::select(daynum, ShiftLength) 

Если вы также хотите указать здесь время начала и окончания смены, вы можете присоединиться (например, добавить left_join(data2) в трубе выше) с data2 на daynum (например). Вы можете назначить фрейм данных на основе начальных нескольких строк кода выше, но я повторю здесь на всякий случай.

data2 <- data1 %>%
  pivot_longer(everything(), names_to = c("day", "event", "num"), values_to = "time", names_pattern = "(\\w+).(Start|End)(\\d)") %>%
  mutate(daynum = cumsum(day != lag(day, default = first(day))) + 1) %>%
  na_if(" ") %>%
  pivot_wider(id_cols = c(daynum, day), names_from = c(event, num), values_from = time)

Вывод

Joining, by = "daynum"
# A tibble: 70 x 7
   daynum ShiftLength day   Start_1  End_1    Start_2  End_2   
    <dbl>       <dbl> <chr> <fct>    <fct>    <fct>    <fct>   
 1      1        8.75 Mon   14:30:00 23:15:00 NA       NA      
 2      2        8.75 Tue   14:30:00 23:15:00 NA       NA      
 3      3        0    Wed   NA       NA       NA       NA      
 4      4        0    Thu   NA       NA       NA       NA      
 5      5       12    Fri   6:30:00  18:30:00 NA       NA      
 6      6       12    Sa    6:30:00  18:30:00 NA       NA      
 7      7       10.2  Sun   6:30:00  16:45:00 NA       NA      
 8      8        0    Mon   NA       NA       NA       NA      
 9      9        0    Tue   NA       NA       NA       NA      
10     10       10    Wed   7:00:00  17:00:00 NA       NA      
11     11        0    Thu   NA       NA       NA       NA      
12     12        0    Fri   NA       NA       NA       NA      
13     13       10    Sa    7:00:00  17:00:00 NA       NA      
14     14        0    Sun   NA       NA       NA       NA      
15     15        0    Mon   NA       NA       NA       NA      
16     16       10    Tue   14:00:00 24:00:00 NA       NA      
17     17        0    Wed   NA       NA       NA       NA      
18     18        0    Thu   NA       NA       NA       NA      
19     19        0    Fri   NA       NA       NA       NA      
20     20        0    Sa    NA       NA       NA       NA      
21     21        0    Sun   NA       NA       NA       NA      
22     22        9    Mon   7:00:00  16:00:00 NA       NA      
23     23        9.5  Tue   7:00:00  16:30:00 NA       NA      
24     24       10    Wed   7:00:00  17:00:00 NA       NA      
25     25        9.5  Thu   7:00:00  16:30:00 NA       NA      
26     26        9.75 Fri   7:00:00  16:45:00 NA       NA      
27     27        0    Sa    NA       NA       NA       NA      
28     28        0    Sun   NA       NA       NA       NA      
29     29        0    Mon   NA       NA       NA       NA      
30     30        0    Tue   NA       NA       NA       NA      
31     31        0    Wed   NA       NA       NA       NA      
32     32        0    Thu   NA       NA       NA       NA      
33     33        9.75 Fri   6:45:00  16:30:00 NA       NA      
34     34        8.5  Sa    14:45:00 23:15:00 NA       NA      
35     35        8.5  Sun   14:45:00 23:15:00 NA       NA      
36     36        9.5  Mon   22:30:00 24:00:00 NA       NA      
37     37        9.5  Tue   0:00:00  8:00:00  22:30:00 24:00:00
38     38        9.5  Wed   0:00:00  8:00:00  22:30:00 24:00:00
39     39        0    Thu   0:00:00  8:00:00  NA       NA      
40     40        0    Fri   NA       NA       NA       NA      
41     41        0    Sa    NA       NA       NA       NA      
42     42        0    Sun   NA       NA       NA       NA      
43     43        9    Mon   14:30:00 23:30:00 NA       NA      
44     44        0    Tue   NA       NA       NA       NA      
45     45        0    Wed   NA       NA       NA       NA      
46     46        9.5  Thu   14:30:00 24:00:00 NA       NA      
47     47        0    Fri   NA       NA       NA       NA      
48     48        0    Sa    NA       NA       NA       NA      
49     49        0    Sun   NA       NA       NA       NA      
50     50       10.5  Mon   7:00:00  17:30:00 NA       NA      
51     51        9.5  Tue   7:00:00  16:30:00 NA       NA      
52     52       10.5  Wed   7:00:00  17:30:00 NA       NA      
53     53        9.5  Thu   7:00:00  16:30:00 NA       NA      
54     54       10.5  Fri   7:00:00  17:30:00 NA       NA      
55     55        9.5  Sa    7:00:00  16:30:00 NA       NA      
56     56        0    Sun   NA       NA       NA       NA      
57     57        0    Mon   NA       NA       NA       NA      
58     58        9.5  Tue   7:00:00  16:30:00 NA       NA      
59     59        9.5  Wed   7:00:00  16:30:00 NA       NA      
60     60        9.5  Thu   7:00:00  16:30:00 NA       NA      
61     61        9.5  Fri   7:00:00  16:30:00 NA       NA      
62     62        0    Sa    NA       NA       NA       NA      
63     63        0    Sun   NA       NA       NA       NA      
64     64        0    Mon   NA       NA       NA       NA      
65     65        0    Tue   NA       NA       NA       NA      
66     66        0    Wed   NA       NA       NA       NA      
67     67        0    Thu   NA       NA       NA       NA      
68     68        0    Fri   NA       NA       NA       NA      
69     69       10.5  Sa    14:00:00 24:00:00 NA       NA      
70     70       10    Sun   0:00:00  0:30:00  14:00:00 24:00:00
...