在 R 中,如何创建时间间隔的直方图?

问题描述 投票:0回答:1

我有一张工作开始和停止时间的表,我想绘制它。输入表如下所示:

工作开始时间 工作完成时间 位置
2024-04-29 18:35:09 2024-04-29 19:36:25 1
2024-04-29 18:33:19 2024-04-29 20:34:40 2
2024-04-29 19:37:17 2024-04-29 19:44:51 1
2024-04-29 21:12:35 2024-04-29 21:31:31 2
2024-04-29 20:31:52 2024-04-29 20:53:23 1

每天有多个条目。有 2 台机器处理作业(用位置 1 和 2 表示),因此给定位置的时间间隔不能重叠。 我想用直方图显示一周中每一天(周一、周二、周三、周四、周五、周六、周日)每台机器每小时的工作负载。我正在考虑 7 个不同的图(每天 1 个),其中每个小时都有一个直方图。因此,如果一项工作于 12:30 开始并于 13:15 结束,则应将 50% 计入 12 小时柱,将 25% 计入 13 小时柱。 由于时间间隔可以与小时标记重叠,我不知道如何处理这个问题。

我正在考虑以下工作流程:

  • 添加一列指示工作的工作日(以便稍后分组)
  • 在小时标记上拆分所有作业(因此 12:30 - 13:15 变成 2 行 -> 12:30-13:00 和 13:00-13:15),这也必须适用于多个拆分工作
  • 计算每个作业的使用情况(工作负载百分比(例如 12:30-13:00 -> 50%)
  • 按工作日和小时进行汇总,并取所有工作负载的平均值

这还有一个问题,机器可能会在多个小时内根本无法工作,但对于上面的平均计算来说,它仍然应该算作 0%。

你有更好的想法或者可以帮助我实现我的想法吗?

非常感谢!

r datetime tidyverse posix
1个回答
0
投票

这是一种使用

tidyverse
(包括
lubridate
)的方法。输出是一个数据框,您可以将其用作图表的基础。

#set initial data as per question
df <- structure(list(job_started_at = c("2024-04-29 18:35:09", "2024-04-29 18:33:19", 
                                        "2024-04-29 19:37:17", "2024-04-29 21:12:35", 
                                        "2024-04-29 20:31:52"
), job_finished_at = c("2024-04-29 19:36:25", "2024-04-29 20:34:40", 
                       "2024-04-29 19:44:51", "2024-04-29 21:31:31", 
                       "2024-04-29 20:53:23"
), position = c(1L, 2L, 1L, 2L, 1L)), class = "data.frame", row.names = c(NA, -5L))

df <- df %>% 
  mutate(across(starts_with("job"), ymd_hms),                  #convert to datetimes
         job_int = interval(job_started_at, job_finished_at))  #calculate intervals

#create a df of the hours to be analysed
hours_df <- tibble(hour = seq(from = ymd_hms("2024-04-29 17:00:00"),
                              to = ymd_hms("2024-04-29 22:00:00"),
                              by = "hour")) %>% 
  mutate(hour_int = interval(hour, hour + hours(1)))           #intervals
         
#for each item, calculate a vector of overlaps, unnest, group and summarise
overlaps_df <- df %>% 
  group_by(position) %>% 
  mutate(overlap = map(job_int, ~rowSums(outer(hours_df$hour_int, ., 
                                               \(x, y) seconds(intersect(x, y))/3600), 
                                         na.rm = TRUE)),
         hour_start = list(hours_df$hour)) %>% 
  unnest_longer(c(overlap, hour_start)) %>% 
  group_by(position, hour_start) %>% 
  summarise(utilisation = sum(overlap))

overlaps_df

# A tibble: 12 × 3
# Groups:   position [2]
   position hour_start          utilisation
      <int> <dttm>                    <dbl>
 1        1 2024-04-29 17:00:00       0    
 2        1 2024-04-29 18:00:00       0.414
 3        1 2024-04-29 19:00:00       0.733
 4        1 2024-04-29 20:00:00       0.359
 5        1 2024-04-29 21:00:00       0    
 6        1 2024-04-29 22:00:00       0    
 7        2 2024-04-29 17:00:00       0    
 8        2 2024-04-29 18:00:00       0.445
 9        2 2024-04-29 19:00:00       1    
10        2 2024-04-29 20:00:00       0.578
11        2 2024-04-29 21:00:00       0.316
12        2 2024-04-29 22:00:00       0    
© www.soinside.com 2019 - 2024. All rights reserved.