You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中排除非业务时段(上周五18点至本周一8点)计算actual_tat?

问题描述

现有如下R数据框:

library(dplyr)
library(lubridate)

ticket_id <- c("id_1234","id_2234","id_1334","id_1244","id_1294",
               "id_1264","id_1634","id_1734","id_1834","id_1934")
created <- c("2024-09-22 22:00:00","2024-09-21 23:00:00","2024-09-19 11:30:00","2024-09-23 6:00:00","2024-09-20 18:30:00",
             "2024-09-15 10:00:00","2024-09-14 23:00:00","2024-09-11 5:30:00","2024-09-16 7:30:00","2024-09-13 19:27:00")
tat <- c(14.4, 38, 106, 6.4, 64, 29, 37, 129.5, 2.8, 66)
df.sample <- data.frame(ticket_id,created,tat,stringsAsFactors=FALSE)
df.sample$created <- ymd_hms(df.sample$created)
df.sample$tat = as.numeric(df.sample$tat)

需要新增actual_tat列,计算规则:

  • 若工单创建时间处于上周五18:00至本周一08:00的非业务时段,从tat中排除创建时间到本周一08:00的时长(若tat小于该排除时长,则actual_tat为0);
  • 若创建时间不在该时段内,actual_tat与tat值相同。

示例:工单创建于周日7:00,tat为14小时,则actual_tat为1小时(14-13,即周一08:00之后的时长)。

尝试的代码未得到正确结果,期望输出为:

ticket_id             created   tat actual_tat
1    id_1234 2024-09-22 22:00:00  14.4        4.4
2    id_2234 2024-09-21 23:00:00  38.0        5.0
3    id_1334 2024-09-19 11:30:00 106.0      106.0
4    id_1244 2024-09-23 06:00:00   6.4        4.4
5    id_1294 2024-09-20 18:30:00  64.0        2.5
6    id_1264 2024-09-15 10:00:00  29.0        7.0
7    id_1634 2024-09-14 23:00:00  37.0        4.0
8    id_1734 2024-09-11 05:30:00 129.5      129.5
9    id_1834 2024-09-16 07:30:00   2.8        2.3
10   id_1934 2024-09-13 19:27:00  66.0        5.5
解决方案

你的代码核心问题在于周一08:00基准点的计算错误,以及依赖星期标签(如"Fri")可能受系统语言影响。以下是修正后的代码:

df.sample %>%
  mutate(
    # 用数字判断星期几(1=周一,7=周日),避免语言依赖
    wday_num = wday(created, week_start = 1),
    hour_num = hour(created),
    # 计算需要排除的时段终点:创建时间之后的第一个周一08:00
    exclude_end = case_when(
      # 周一00:00-08:00:当天08:00
      wday_num == 1 & hour_num < 8 ~ floor_date(created, "day") + hours(8),
      # 周五18:00及以后、周六、周日:下周一08:00
      (wday_num == 5 & hour_num >= 18) | wday_num %in% c(6,7) ~ floor_date(created, "week", week_start = 1) + weeks(1) + hours(8),
      # 其他情况:不属于非业务时段,设为NA
      TRUE ~ NA_POSIXct_
    ),
    # 计算需要排除的时长(小时)
    exclude_hours = as.numeric(difftime(exclude_end, created, units = "hours")),
    # 计算actual_tat:排除非业务时段,确保结果不小于0
    actual_tat = case_when(
      !is.na(exclude_hours) ~ pmax(tat - exclude_hours, 0),
      TRUE ~ tat
    )
  ) %>%
  # 保留原列和结果列,移除中间计算列(可选)
  select(ticket_id, created, tat, actual_tat)

代码说明

  1. 星期判断:用wday(..., week_start=1)将周一设为星期1,避免系统语言对标签的影响,判断更可靠。
  2. 排除时段终点计算:
    • 周一早8点前创建的工单,排除到当天8点;
    • 周五晚6点后、周六、周日创建的工单,排除到下周一8点;
  3. 时长计算:用difftime计算创建时间到排除终点的小时数,再用pmax确保actual_tat不会为负数。
  4. 结果整理:可选移除中间计算列,保留需要的字段。

运行上述代码后,即可得到你期望的输出结果。

内容的提问来源于stack exchange,提问作者Sharath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:52:33