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

基于人口比例及最小/最大限制在R中实现区域帽子分配

Absolutely, this is a classic constrained proportional allocation problem, and we can solve it efficiently with data.table using an iterative approach that respects both population weights and your MIN/MAX constraints. Let's walk through a step-by-step implementation tailored to your data:

Step 1: Set Up Your Data

First, let's load the required library and define your dataset (I've cleaned up the formatting a bit for readability):

library(data.table)
dt1 <- data.table(
  ZONE = c("A34","G345","H62","D563","T63","P983","S24","J54","W953","L97","V56","R99"),
  POPULATION = c(40,110,80,70,90,90,130,140,80,30,80,50),
  MIN = c(1,0,0,1,0,1,0,1,1,0,1,1),
  MAX = c(10,9,2,11,12,8,5,3,2,0,8,8)
)

Step 2: Implement the Iterative Allocation

The core idea is to repeatedly allocate hats in two phases: first, fill all regions up to their minimum requirement, then distribute any remaining hats proportionally to regions that still have capacity below their maximum. We'll loop until all hats are allocated or no more regions can accept additional hats.

# Initialize variables
total_hats <- 50
dt1[, ALLOCATED := 0]
remaining_hats <- total_hats

# Optional pre-check: Ensure total minimum doesn't exceed available hats
if (sum(dt1$MIN) > total_hats) {
  stop("Error: Total minimum required hats exceed the 50 available. Adjust constraints or hat count.")
}

# Iterative allocation loop
while (remaining_hats > 0) {
  # Phase 1: Fill regions to their MIN requirement first
  dt1[, deficit := pmax(MIN - ALLOCATED, 0)]
  total_deficit <- sum(dt1$deficit)
  
  if (total_deficit > 0) {
    if (remaining_hats >= total_deficit) {
      # We have enough hats to cover all deficits
      dt1[, ALLOCATED := ALLOCATED + deficit]
      remaining_hats <- remaining_hats - total_deficit
    } else {
      # Not enough hats to cover all deficits: allocate proportionally by population
      eligible_deficit <- dt1[deficit > 0]
      eligible_deficit[, weight := POPULATION / sum(POPULATION)]
      eligible_deficit[, add := round(remaining_hats * weight)]
      
      # Fix rounding errors to ensure total added equals remaining hats
      eligible_deficit[order(add, -POPULATION), 
                      add := add + c(remaining_hats - sum(add), rep(0, .N-1))]
      
      dt1[eligible_deficit, ALLOCATED := ALLOCATED + add, on = .(ZONE)]
      remaining_hats <- 0
    }
    dt1[, deficit := NULL]
    next
  }
  
  # Phase 2: Distribute remaining hats to regions with available capacity (below MAX)
  dt1[, available_capacity := pmax(MAX - ALLOCATED, 0)]
  eligible_extra <- dt1[available_capacity > 0]
  
  if (nrow(eligible_extra) == 0) {
    warning(paste(remaining_hats, "hats could not be allocated: all regions are at their MAX limit."))
    break
  }
  
  # Calculate proportional allocations
  eligible_extra[, weight := POPULATION / sum(POPULATION)]
  eligible_extra[, add := round(remaining_hats * weight)]
  
  # Fix rounding errors
  eligible_extra[order(add, -POPULATION), 
                add := add + c(remaining_hats - sum(add), rep(0, .N-1))]
  
  # Ensure we don't exceed each region's MAX capacity
  eligible_extra[, add := pmin(add, available_capacity)]
  total_added <- sum(eligible_extra$add)
  
  # Update allocations and remaining hats
  dt1[eligible_extra, ALLOCATED := ALLOCATED + add, on = .(ZONE)]
  remaining_hats <- remaining_hats - total_added
  
  dt1[, available_capacity := NULL]
}

Step 3: Verify the Results

Let's check the final allocations to make sure they meet all constraints and sum to 50:

# View the final allocations
dt1[, .(ZONE, POPULATION, MIN, MAX, ALLOCATED)]

# Check total allocated hats
cat("Total hats allocated:", sum(dt1$ALLOCATED), "\n")

# Verify all constraints are met
cat("All regions meet MIN/MAX constraints:", 
    all(dt1$ALLOCATED >= dt1$MIN & dt1$ALLOCATED <= dt1$MAX), "\n")

Key Notes

  • Priority to Minimums: We always fill regions to their MIN first, since those are hard lower limits.
  • Handling Rounding: The code adjusts for rounding errors to ensure we never allocate more or fewer hats than intended.
  • Capacity Checks: We skip regions that are already at their MAX limit when distributing extra hats.
  • Edge Cases: The pre-check ensures we don't waste time trying to allocate hats when the total minimum requirement exceeds the available hats. If the total maximum capacity is less than 50, the loop will warn you about unallocated hats.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:43:10