首页 > 解决方案 > R函数根据单位值分配固定资源

问题描述

我正在尝试在 R 中创建一个函数,以根据这些单位提供的值分配固定数量的单位。我设置了以下示例数据框。

fruit <- c("apple","orange","bannana","cherry")
units_of_mass <- c(9, 11, 16, 7)
health_pts <- c(5, 3, 6, 1)
diet_plan <- data.frame(fruit, units_of_mass, health_pts)
total_units_desired <- 32

所以我想做的是根据分配给每个水果的健康点分配所需的总单位,从最高健康点开始。

我尝试使用 dplyr 但卡住了

fruit_detail <- diet_plan %>%

arrange(fruit, health_pts) %>%

mutate(
  cum_units = cumsum(units_of_mass) - units_of_mass,
  can_allocate = total_units_desired - cum_units,
  allocated = ifelse(can_allocate <= 0, 0, ifelse(can_allocate >= 
  cum_units, cum_units))
 )

执行此操作的简单方法是按生命值排列并减去单位,直到用完 total_units_desired,如下所示:

## iterate on allocations
diet_plan <- setDT(diet_plan)

max <- max(diet_plan$health_pts)

allocation_1 <- subset(diet_plan, health_pts == max)
allocation_1[, units_allocated := ifelse(total_units_desired > 
               units_of_mass, units_of_mass, total_units_desired)]

remaining_units <- ifelse(total_units_desired - allocation_1$units_allocated 
                   > 0, total_units_desired - allocation_1$units_allocated, 
                   0)

diet_plan <- subset(diet_plan, health_pts < max)
max <- max(diet_plan$health_pts)

allocation_2 <- subset(diet_plan, health_pts == max)
allocation_2[, units_allocated := ifelse(remaining_units > units_of_mass, 
                                  units_of_mass, remaining_units)]

remaining_units <- ifelse(remaining_units - allocation_2$units_allocated > 
                   0, remaining_units - allocation_2$units_allocated, 0)

diet_plan <- subset(diet_plan, health_pts < max)
max <- max(diet_plan$health_pts)

allocation_3 <- subset(diet_plan, health_pts == max)
allocation_3[, units_allocated := ifelse(remaining_units > units_of_mass, 
                                  units_of_mass, remaining_units)]

remaining_units <- ifelse(remaining_units - allocation_3$units_allocated > 
                   0, remaining_units - allocation_3$units_allocated, 0)

diet_plan <- subset(diet_plan, health_pts < max)
max <- max(diet_plan$health_pts)

allocation_4 <- subset(diet_plan, health_pts == max)
allocation_4[, units_allocated := ifelse(remaining_units > units_of_mass, 
units_of_mass, remaining_units)]

result <- rbind(allocation_1, allocation_2, allocation_3, allocation_4)

 fruit units_of_mass health_pts units_allocated
bannana        16          6              16
apple           9          5               9
orange         11          3               7
cherry          7          1               0

标签: r

解决方案


您提出问题的方式,我们可以按 排序health_pts,然后找到 的累积总和,如果我们取该项目和它上面的所有项目units_of_mass,这就是总和。units_allocated然后我们可以filter只拿那些不会让我们超过限制的物品total_units_desired

然后,剩余的行可以分配最大数量的单元:

diet_plan_sum %>%
    arrange(desc(health_pts)) %>%                # Sort by health_pts
    mutate(cum_sum = cumsum(units_of_mass)) %>%  # Calculate total cumulative units
    filter(cum_sum < total_units_desired) %>%    # Drop items over allocation limit
    mutate(units_allocated = units_of_mass) %>%  # For remaining rows, allocate max
    select(-cum_sum)                             # Drop cum_sum variable

    fruit units_of_mass health_pts units_allocated
1 bannana            16          6              16
2   apple             9          5               9

如果您想分配剩余的单位,我们可以对上述内容进行一些更改:

首先,我们找到超过阈值的第一行:这是唯一具有部分值的行。然后我们可以将它的units_allocated值设置为total - the proceeding row's value,也就是余数。

对于每隔一行,我们检查累积和是否大于阈值:如果是,则设置units_allocated为 0,如果不是,则设置units_allocatedunits_of_mass

diet_plan_sum %>%
    arrange(desc(health_pts)) %>%
    mutate(cum_sum = cumsum(units_of_mass),
           # Find the first row where we go over the threshold, set it to remainder
           units_allocated = if_else(cum_sum > total_units_desired & lag(cum_sum) < total_units_desired,
                                     total_units_desired - lag(cum_sum),
                                     if_else(cum_sum > total_units_desired,
                                             0,
                                             units_of_mass))) %>%
    select(-cum_sum) # Drop cum_sum variable

    fruit units_of_mass health_pts units_allocated
1 bannana            16          6              16
2   apple             9          5               9
3  orange            11          3               7
4  cherry             7          1               0

推荐阅读