【问题标题】:How do create start and end time intervals with specific conditions when more than one start and end per day and overnight当每天和一夜之间有多个开始和结束时,如何创建具有特定条件的开始和结束时间间隔
【发布时间】:2020-03-06 12:42:31
【问题描述】:

我有一个包含每个工作日工作时间的数据框。我每天都有开始和结束时间。当员工在同一天工作两次时,就会出现问题。例如,他从周五晚上 10 点开始工作,周六早上 8 点下班,但周六晚上 10 点又开始工作。 我的数据集现在的结构是这样的:

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 设置开始和结束时间。我还添加了所有日期的日期(as.POSICxt)当员工一天只工作一次时,它可以工作,但当他工作两次时就不行。因为有时我的结束时间实际上是结束时间(因为星期一 24:00 是结束时间)但有时它会持续一夜(如星期五和星期六),所以 24:00 不是结束时间。是否有设置每次开始时间为 00 时开始时间应为前一天的 start2 的功能?或者我该如何解决这个问题?目标是创建休息时间并标记每个班次,按开始时间如夜间、晚班等和 difftime。同样对于那些工作两次的人,如果我削减并标记开始时间来定义轮班,因为员工有两个开始时间,所以我每周多轮班结束,这实际上是不正确的。

所需的输出是在一列中显示星期几、开始时间、结束时间、轮班长度、轮班类型(关闭、早上、深夜、晚上),然后在每天都有这些之后能够在每周级别和每月级别进行一些计算。

如果有人能给我一些建议,我将非常感激。谢谢

【问题讨论】:

  • 欢迎来到 Stack Overflow。帮助我们帮助您,以人们可以使用的方式提供数据。从这里开始stackoverflow.com/questions/5963269/… 显示一些代码而不是描述您正在尝试的内容。显示预期结果。
  • @Sunshine_student 您可以尝试再次粘贴数据吗?它看起来像被切断并且看起来不完整。也许你可以为前 10 行数据做dput(head(data1, 10))
  • @Ben,像这样吗?这里它们仍然是因子,我为每一天插入一个日期并将它们分成两个,一个作为日期,另一个作为时间。谢谢你

标签: r datetime intervals lubridate difftime


【解决方案1】:

这并不容易,也不是最好的考虑方法。但是,如果主要目标是计算班次的长度,也许这可能会有所帮助。

首先,我将使用pivot_longer 放入一个可以根据日期、事件(开始或结束)和班次进行评估的表格。由于日期不可用,因此有一个日期列也会有所帮助。

似乎有空格 - 这些是NA

使用lubridate 函数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) 

如果您还想在此处也有轮班开始和结束时间,您可以通过daynum(例如)加入(例如,在上面的管道中添加left_join(data2))与data2。您可以根据上面最初的几行代码分配数据框,但我会在这里重复以防万一。

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

【讨论】:

  • 嗨,本,非常感谢您的帮助。我试图理解它,但实际上我无法理解。我添加了每个员工的识别号以及每天的日期,以查看它是否变得更容易,但我无法找到一种方法来计算轮班从 00:00 开始的时间来计算前一个的开始时间 2 和结束时间 2天。
猜你喜欢
  • 2022-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 2016-02-03
  • 1970-01-01
相关资源
最近更新 更多