在R中计算排除非工作时间/周末后的客户工单处理时长
计算客户查询的有效工作时长(排除非工作时间)
需求回顾
针对包含客户ID、任务类型、时间戳的数据框,需为每个客户计算:
- 第一条
Task == "New"的时间,与最后一条Task == "Closed"的时间之间的有效工作分钟数 - 工作时间规则:中欧时间(CET/CEST,自动处理夏令时)周一至周五8:00-17:00,排除非工作时段、周末
解决方案步骤
我们可以用dplyr做数据分组提取,lubridate处理时区转换,bizdays包快速计算工作时长,代码如下:
1. 加载依赖包
library(dplyr) library(lubridate) library(bizdays)
2. 提取关键时间点
按客户分组,提取每个客户的首次"New"时间和末次"Closed"时间:
customer_time_points <- df1 %>% group_by(ID) %>% summarise( new_utc = first(Date_time[Task == "New"]), last_closed_utc = last(Date_time[Task == "Closed"]), .groups = "drop" )
3. 时区转换为中欧时间
原数据是UTC时区,转换为Europe/Berlin时区(自动识别CET/CEST夏令时切换):
customer_time_points <- customer_time_points %>% mutate( new_cet = with_tz(new_utc, tzone = "Europe/Berlin"), last_closed_cet = with_tz(last_closed_utc, tzone = "Europe/Berlin") )
4. 定义工作时间规则
创建符合要求的工作日历,指定周末、工作时段:
# 创建工作日历:排除周六周日,工作时间8:00-17:00 cet_work_calendar <- create.calendar( name = "CET_Workdays", weekdays = c("saturday", "sunday"), workhours = workhours(from = "08:00", to = "17:00"), start.date = min(customer_time_points$new_cet), end.date = max(customer_time_points$last_closed_cet) )
5. 计算有效工作分钟数
bizhours函数直接返回两个时间之间的工作小时数,乘以60转换为分钟:
customer_work_duration <- customer_time_points %>% mutate( work_minutes = bizhours(new_cet, last_closed_cet, cet_work_calendar) * 60 )
结果示例
运行后customer_work_duration会包含每个客户的ID、关键时间点,以及最终的有效工作分钟数。比如示例中的customer2,会自动忽略4月到8月之间的非工作时段、周末,只计算周一至周五8-17点的时长。
替代方案(无bizdays包)
如果不想额外安装包,可以通过循环遍历每一天,判断是否为工作日,再计算当天的有效工作时长总和,代码示例如下(仅作参考,推荐用bizdays更高效):
calc_work_minutes <- function(start, end) { total_min <- 0 current_day <- floor_date(start, "day") end_day <- floor_date(end, "day") while(current_day <= end_day) { # 判断是否为工作日(周一至周五) if(wday(current_day, week_start = 1) %in% 1:5) { # 当天工作时段的起止 work_start <- current_day + hours(8) work_end <- current_day + hours(17) # 计算当天的有效时间段 period_start <- max(start, work_start) period_end <- min(end, work_end) if(period_start < period_end) { total_min <- total_min + as.duration(period_end - period_start)/dminutes(1) } } current_day <- current_day + days(1) } return(total_min) } # 应用函数 customer_work_duration <- customer_time_points %>% rowwise() %>% mutate(work_minutes = calc_work_minutes(new_cet, last_closed_cet)) %>% ungroup()
内容的提问来源于stack exchange,提问作者Lazline Brown
相关产品推荐
相关产品推荐

