Python DataFrame订单与卷材分配问题求助:代码逻辑修正
卷材订单分配逻辑修正
问题背景
现有两个DataFrame,分别存储订单详情和卷材(coil)详情,需完成订单到卷材的分配,满足以下规则:
- 每个订单对分配的卷材重量有**最小(TOP_MIN_COIL_WT)和最大(TOP_MAX_COIL_WT)**范围限制,分配的单份卷材重量必须落在该区间内
- 允许超额10%分配订单需求,以充分利用卷材
订单DataFrame(order为唯一ID)
order bct TOP_MIN_COIL_WT TOP_MAX_COIL_WT demand 0 o1 bct2 3 25 12.000 1 o2 bct2 3 25 11.340 2 o3 bct2 3 25 9.460 3 o4 bct2 3 25 6.540 4 o5 bct1 4 7 51.000 5 o6 bct1 5 7 51.000 6 o7 bct1 3 5 34.000 7 o8 bct1 3 5 22.260 8 o9 bct1 4 6 17.000 9 o10 bct1 5 7 17.000 10 o11 bct1 3 5 17.000 11 o12 bct1 4 7 6.605
卷材DataFrame(mc为唯一编号)
mc bct coiltons 0 c1 bct2 24.45 1 c2 bct2 24.10 2 c3 bct1 17.08 3 c4 bct1 17.04 4 c5 bct1 17.03 5 c6 bct1 17.01 6 c7 bct1 16.98 7 c8 bct1 16.98 8 c9 bct1 15.88 9 c10 bct1 15.76 10 c11 bct1 15.72 11 c12 bct1 15.65 12 c13 bct1 15.59 13 c14 bct1 13.16 14 c15 bct1 13.14
现有代码问题分析
原代码的核心问题集中在splitNumber函数逻辑错误和分配流程的不合理:
splitNumber函数逻辑混乱:- 初始判断条件错误,未正确区分卷材重量是否符合范围
- 拆分份数的计算范围搞反,导致无法找到有效拆分份数
- 未处理无法拆分的情况(返回0),导致无效分配
- 分配流程问题:
- 拆分卷材时错误地生成多份记录,但仅扣除一份的重量,剩余卷材的处理逻辑缺失
- 未实现超额10%分配的规则
- 迭代时直接修改原DataFrame,可能导致后续迭代数据异常
修正后的代码
import numpy as np import pandas as pd import math def splitNumber(n, a, b): # 卷材重量小于最小允许值,无法满足要求,返回0(不能拆分/使用) if n < a: return 0 # 卷材重量在允许范围内,无需拆分,返回1 if a <= n <= b: return 1 # 计算有效拆分份数的范围:i需满足 n/b < i < n/a min_i = math.ceil(n / b) max_i = math.floor(n / a) # 范围无效,无法拆分 if min_i > max_i: return 0 # 从大到小找最大有效份数(优先拆分更多小份,提升利用率) for i in range(max_i, min_i - 1, -1): part_weight = n / i if a <= part_weight <= b: return i # 无有效拆分方式 return 0 # 复制卷材DataFrame,避免修改原数据 dfmc_copy = dfmc.copy().reset_index(drop=True) outputRows = [] for _, order_row in dfo.iterrows(): order_id = order_row['order'] bct_type = order_row['bct'] min_coil_wt = order_row['TOP_MIN_COIL_WT'] max_coil_wt = order_row['TOP_MAX_COIL_WT'] demand = order_row['demand'] # 允许超额10%分配 max_alloc = demand * 1.1 remaining_demand = demand # 筛选当前bct类型且剩余重量>0的卷材 available_coils = dfmc_copy[(dfmc_copy['bct'] == bct_type) & (dfmc_copy['coiltons'] > 0.001)].reset_index(drop=True) for _, coil_row in available_coils.iterrows(): coil_id = coil_row['mc'] coil_weight = coil_row['coiltons'] coil_idx = dfmc_copy[dfmc_copy['mc'] == coil_id].index[0] if remaining_demand <= 0: break # 卷材重量符合订单范围,直接分配 if min_coil_wt <= coil_weight <= max_coil_wt: # 计算可分配量:不超过剩余需求,也不超过超额上限 alloc = min(remaining_demand, coil_weight, max_alloc - (demand - remaining_demand)) outputRows.append([ order_id, bct_type, coil_id, alloc, coil_weight, 0 ]) # 更新剩余需求和卷材重量 remaining_demand -= alloc dfmc_copy.at[coil_idx, 'coiltons'] = coil_weight - alloc continue # 需要拆分卷材 split_count = splitNumber(coil_weight, min_coil_wt, max_coil_wt) if split_count == 0: continue # 无法拆分,跳过该卷材 part_weight = coil_weight / split_count # 计算可分配量:不超过剩余需求、单份重量,且不超过超额上限 alloc = min(remaining_demand, part_weight, max_alloc - (demand - remaining_demand)) # 记录分配(仅当前订单使用的那一份) outputRows.append([ order_id, bct_type, f"{coil_id}_1", alloc, coil_weight, 1 ]) # 更新剩余需求和卷材重量 remaining_demand -= alloc dfmc_copy.at[coil_idx, 'coiltons'] = coil_weight - alloc outputColumns = ['order', 'typebc', 'coil', 'allocatedQuantity', 'ton', 'flag'] df_output = pd.DataFrame(outputRows, columns=outputColumns)
修正说明
splitNumber函数优化:- 明确判断逻辑,先排除无法使用的卷材
- 正确计算拆分份数的有效范围,确保每份重量落在订单要求区间内
- 返回0表示无法拆分,避免无效分配
- 分配流程优化:
- 复制卷材DataFrame,避免修改原始数据影响后续操作
- 实现超额10%分配规则,限制总分配量不超过需求的110%
- 拆分卷材时仅记录当前订单使用的部分,剩余卷材重量保留在DataFrame中待后续订单分配
- 筛选可用卷材时增加重量阈值(>0.001),避免处理几乎为空的卷材
内容的提问来源于stack exchange,提问作者Manglu
相关产品推荐
相关产品推荐

