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

R语言:如何在任务工时抽样分配中实现指定人员固定工时?

带最低工时要求的任务分配方案

首先需要明确:当前Manager角色的任务总工时为1+10+30=41,但要求Michael至少40工时、Jose至少11工时,两者总和40+11=51超过了Manager任务的总工时,存在逻辑矛盾,无法同时满足。以下方案基于修正后的合理要求(例如调整Jose最低工时为1,或增加Manager任务总工时),实现带最低要求的抽样分配。

前提数据准备

先加载并生成原始数据:

library(bizdays)
library(tidyverse)

# 生成2023年工作日人员排班表
from_date <- "2023-01-01"
to_date <- "2023-12-31"
create.calendar(name = "cal23", holidays = integer(0), weekdays = c("saturday", "sunday"))
daty2023 <- bizseq(from_date, to_date, "cal23") %>% as.data.frame()
daty2023 <- daty2023 %>% mutate(resource = "Michael", role = "Manager")
daty20231 <- daty2023 %>% mutate(resource = "Jose", role = "Manager")
daty20232 <- daty2023 %>% mutate(resource = "Jakub", role = "Researcher")
daty2023 <- rbind(daty2023, daty20231, daty20232)
colnames(daty2023) <- c("date", "resource", "role")
daty2023$date <- as.Date(daty2023$date)

# 生成任务列表
tasklist <- data.frame(
  task = c("Task1", "Task2", "Task3", "Task4"),
  sdate = c("2023-01-12", "2023-04-18", "2023-08-25", "2023-11-03"),
  fdate = c("2023-01-12", "2023-04-25", "2023-09-26", "2023-12-29"),
  resource = c("Manager", "Manager", "Researcher", "Manager")) %>%
  mutate(mandays = as.integer(c("1", "10", "20", "30")),
         sdate = as.Date(sdate),
         fdate = as.Date(fdate))

可行解决方案:分阶段抽样分配

1. 定义最低工时要求

这里假设修正后的合理要求:Michael≥40、Jose≥1、Jakub≥10(总和51≤61,剩余10工时可灵活分配):

min_alloc <- tibble(
  resource = c("Michael", "Jose", "Jakub"),
  min_days = c(40, 1, 10)
)

2. 第一阶段:优先分配最低工时

从符合角色和任务时间窗口的可用日期中,为每个资源抽取最低要求的工时:

final_df <- data.frame()
temp_daty <- daty2023  # 复制一份用于操作,避免修改原始数据

# 遍历每个资源,分配最低工时
for (res in min_alloc$resource) {
  # 获取当前资源的角色
  role <- temp_daty %>% filter(resource == res) %>% pull(role) %>% unique()
  # 获取该角色对应的所有任务
  role_tasks <- tasklist %>% filter(resource == role)
  # 筛选该资源在任务时间窗口内的可用日期
  available_days <- temp_daty %>% 
    filter(resource == res) %>%
    inner_join(role_tasks, by = character()) %>%
    filter(date >= sdate & date <= fdate)
  
  # 抽取最低要求的天数
  min_sample <- available_days %>% 
    sample_n(size = min_alloc$min_days[min_alloc$resource == res]) %>%
    select(date, resource, role, task)
  
  # 加入结果集
  final_df <- bind_rows(final_df, min_sample)
  # 从可用池中移除已分配的日期,避免重复分配
  temp_daty <- temp_daty %>% anti_join(min_sample, by = c("date", "resource"))
}

3. 第二阶段:分配剩余工时

计算每个任务剩余未分配的工时,从剩余可用日期中抽样分配:

# 计算每个任务已分配的工时,得到剩余需要分配的数量
remaining_tasks <- tasklist %>%
  left_join(final_df %>% group_by(task) %>% summarise(assigned = n()), by = "task") %>%
  mutate(remaining = mandays - ifelse(is.na(assigned), 0, assigned)) %>%
  filter(remaining > 0)

# 分配剩余工时
for (i in 1:nrow(remaining_tasks)) {
  remaining_sample <- temp_daty %>%
    filter(role == remaining_tasks$resource[i],
           date >= remaining_tasks$sdate[i],
           date <= remaining_tasks$fdate[i]) %>%
    sample_n(size = remaining_tasks$remaining[i]) %>%
    mutate(task = remaining_tasks$task[i]) %>%
    select(date, resource, role, task)
  
  final_df <- bind_rows(final_df, remaining_sample)
  temp_daty <- temp_daty %>% anti_join(remaining_sample, by = c("date", "resource"))
}

4. 验证分配结果

检查每个资源的总工时和每个任务的完成情况:

# 查看各资源总工时
final_df %>% group_by(resource) %>% summarise(total_mandays = n())

# 查看各任务分配工时
final_df %>% group_by(task) %>% summarise(assigned_mandays = n())

若坚持原最低要求(Michael≥40、Jose≥11)

需调整Manager任务的总工时,例如将Task4的mandays从30改为40,使Manager总工时达到51:

tasklist <- tasklist %>% mutate(mandays = ifelse(task == "Task4", 40, mandays))

之后重复上述分阶段分配流程即可满足要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:35:34