在R语言中如何基于起止时间创建时间直方图并统计时段在岗员工数
嘿,这两个需求用R的tidyverse工具链就能完美解决,我一步步给你讲清楚~
首先咱们先把你的数据转成R里能正确识别的格式,用lubridate包处理时间超方便:
library(tidyverse) library(lubridate) # 构建你的员工数据框 DF <- tibble( EmployeeNum = c(123, 342, 876), Start_datetime = ymd_hms(c("2012-02-01 07:30:00", "2012-02-01 08:00:00", "2012-02-01 10:45:00")), End_datetime = ymd_hms(c("2012-02-01 17:45:00", "2012-02-01 17:45:00", "2012-02-01 18:45:00")) )
1. 统计每天每小时的在岗员工数量
这个需求的核心是:找出每个小时区间内,有多少员工的工作时间覆盖了这个小时。咱们分三步来做:
步骤1:生成需要统计的所有小时区间
首先确定统计的时间范围,从最早的工作开始时间的整点,到最晚的工作结束时间的整点,每小时生成一个区间:
# 确定时间范围的首尾整点 min_time <- floor_date(min(DF$Start_datetime), "hour") max_time <- ceiling_date(max(DF$End_datetime), "hour") # 生成所有要统计的小时区间,整理成日期+小时的格式 hourly_intervals <- tibble(Hour_start = seq(min_time, max_time, by = "hour")) %>% mutate( Date = as.Date(Hour_start), Hour = format(Hour_start, "%H:%M"), # 转成你要的00:00格式 Hour_end = Hour_start + hours(1) )
步骤2:匹配每个员工覆盖的小时区间
对每个员工,找出他们工作期间覆盖的所有完整小时,然后把这些小时和员工ID关联起来:
employee_hours <- DF %>% rowwise() %>% mutate( # 生成该员工工作期间的所有整点小时 covered_hours = list(seq(floor_date(Start_datetime, "hour"), ceiling_date(End_datetime, "hour") - hours(1), by = "hour")) ) %>% unnest(covered_hours) %>% # 把列表展开成每行一个小时 mutate( Date = as.Date(covered_hours), Hour = format(covered_hours, "%H:%M") ) %>% select(EmployeeNum, Date, Hour)
步骤3:统计每个小时的在岗人数
最后把生成的小时区间和员工覆盖的小时合并,统计每个小时的员工数,同时确保即使某个小时没人在岗,也会显示0:
final_stats <- hourly_intervals %>% select(Date, Hour) %>% left_join(employee_hours %>% count(Date, Hour, name = "NumberofEmployeesWorking"), by = c("Date", "Hour")) %>% mutate(NumberofEmployeesWorking = replace_na(NumberofEmployeesWorking, 0)) %>% arrange(Date, Hour) # 查看结果 print(final_stats)
运行后你会得到完全符合要求的输出格式,比如2012-02-01的07:00会有1个员工(123号),08:00开始有2个,以此类推。
2. 创建工作时间区间的时间直方图
这里有两种常见的展示方式,根据你的需求选就行:
方式1:按小时统计的柱状直方图
直接用上面生成的employee_hours数据,统计每个小时的在岗人数,画成柱状图:
ggplot(employee_hours, aes(x = Hour)) + geom_bar(fill = "#2ecc71", width = 0.8) + labs( title = "Hourly Count of Working Employees", x = "Hour of Day", y = "Number of Employees" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) # 让小时标签倾斜,避免重叠
如果你的数据有多天,还可以按日期分面展示:
ggplot(employee_hours, aes(x = Hour)) + geom_bar(fill = "#3498db", width = 0.8) + facet_wrap(~Date) + # 按日期拆分面板 labs( title = "Hourly Employee Count by Date", x = "Hour of Day", y = "Number of Employees" ) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1))
方式2:展示每个员工的工作区间(叠加式)
如果想更直观看到每个员工的工作时间段分布,可以用线段图展示:
DF %>% mutate(EmployeeID = factor(EmployeeNum)) %>% ggplot(aes(y = EmployeeID, x = Start_datetime, xend = End_datetime)) + geom_segment(size = 3, color = "#e74c3c") + labs( title = "Employee Work Time Intervals", x = "Datetime", y = "Employee Number" ) + theme_minimal()
这个图能清晰看到每个员工的起止时间,以及不同员工的工作时间重叠情况。
内容的提问来源于stack exchange,提问作者Essi Shams
相关产品推荐
相关产品推荐

