我有一个数据框问题。我有两个数据框。第一个数据帧包含订单详细信息,第二个数据帧包含线圈详细信息。我需要将订单分配给线圈以满足订单的需求。每个订单都有最小和最大卷重范围,因此在分配订单时,我需要维护最小和最大吨数。例如,假设订单需求为14,最小和最大范围分别为10和14,可用卷材重量为24,那么我需要将24吨卷材分成两部分,每部分12,然后从一个12,我将分配 12,然后从第 2 个 12 开始,我将分配 2 以满足 14 的需求。我的第一个数据帧(订单表示唯一的订单 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
第二个datafarme(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
为了解决分离问题,我定义了一个函数。我已经写了代码,但是分配不正确。另请注意,我们可以满足超过充分利用线圈的需求(额外 10%)。我的代码如下
import numpy as np
import pandas as pd
def splitNumber(n, a, b):
if n < a or n < b:
return 1
lb = int(np.floor(n/a))
ub = int(np.floor(n/b))
for i in range(ub, lb+1):
s = n/i
if (s > a) and (s < b):
return i
return 1
outputRows = []
for index, row in dfo.iterrows():
order = row['order']
bct = row['bct']
minton = row['TOP_MIN_COIL_WT']
maxton = row['TOP_MAX_COIL_WT']
dem = row['demand']
matchedcoil = dfmc[dfmc['bct'] == bct]
for index, row in matchedcoil.iterrows():
coil = row['mc']
coilt = row['coiltons']
if (coilt > minton) and (coilt < maxton):
alloc = min(dem, coilt)
outputRows.append([order, bct, coil, alloc, coilt, 0])
dem = dem - alloc
coilt = coilt - alloc
dfmc.at[index, 'coiltons'] = coilt
if dem == 0:
break
else:
noParts = splitNumber(coilt, minton, maxton)
if noParts > 0:
alloc = min(dem, coilt / noParts)
for part in range(1, noParts + 1):
outputRows.append([order, bct, f"{coil}_{part}", alloc, coilt, 1])
dem = dem - alloc
coilt = coilt - alloc
dfmc.at[index, 'coiltons'] = coilt
if dem == 0:
break
outputColumns = ['order', 'typebc', 'coil', 'allocatedQuantity', 'ton', 'flag']
df_output = pd.DataFrame(outputRows, columns=outputColumns)
请帮忙。
问题出在分裂和分配逻辑上。您可以通过改进
splitNumber
函数以返回指定 min-max
范围内的正确零件数来解决此问题。它更新了主分配循环,以处理线圈被拆分到多个订单的情况,同时仍满足 10% 的超额限制。我建议这样做:
import numpy as np
import pandas as pd
def splitNumber(n, a, b):
lb = int(np.ceil(n / b))
ub = int(np.floor(n / a))
for i in range(lb, ub + 1):
if a <= n / i <= b:
return i
return 1
dfo = pd.DataFrame({
'order': ['o1', 'o2', 'o3', 'o4', 'o5', 'o6', 'o7', 'o8', 'o9', 'o10', 'o11', 'o12'],
'bct': ['bct2', 'bct2', 'bct2', 'bct2', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1'],
'TOP_MIN_COIL_WT': [3, 3, 3, 3, 4, 5, 3, 3, 4, 5, 3, 4],
'TOP_MAX_COIL_WT': [25, 25, 25, 25, 7, 7, 5, 5, 6, 7, 5, 7],
'demand': [12, 11.34, 9.46, 6.54, 51, 51, 34, 22.26, 17, 17, 17, 6.605]
})
dfmc = pd.DataFrame({
'mc': ['c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10', 'c11', 'c12', 'c13', 'c14', 'c15'],
'bct': ['bct2', 'bct2', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1', 'bct1'],
'coiltons': [24.45, 24.1, 17.08, 17.04, 17.03, 17.01, 16.98, 16.98, 15.88, 15.76, 15.72, 15.65, 15.59, 13.16, 13.14]
})
outputRows = []
for _, order_row in dfo.iterrows():
order = order_row['order']
bct = order_row['bct']
minton = order_row['TOP_MIN_COIL_WT']
maxton = order_row['TOP_MAX_COIL_WT']
dem = order_row['demand']
max_allowable = dem * 1.1
matched_coils = dfmc[dfmc['bct'] == bct].sort_values('coiltons', ascending=False)
for coil_idx, coil_row in matched_coils.iterrows():
coil = coil_row['mc']
coilt = coil_row['coiltons']
while coilt > 0 and dem > 0:
if minton <= coilt <= maxton:
alloc = min(dem, coilt)
outputRows.append([order, bct, coil, alloc, coilt, 0])
dem -= alloc
coilt -= alloc
else:
noParts = splitNumber(coilt, minton, maxton)
if noParts > 1:
part_weight = coilt / noParts
alloc = min(dem, part_weight)
for part in range(noParts):
outputRows.append([order, bct, f"{coil}_{part+1}", alloc, part_weight, 1])
dem -= alloc
coilt -= alloc
if dem <= 0:
break
else:
break
dfmc.at[coil_idx, 'coiltons'] = coilt
if dem <= 0:
break
if dem <= 0:
break
outputColumns = ['order', 'typebc', 'coil', 'allocatedQuantity', 'ton', 'flag']
df_output = pd.DataFrame(outputRows, columns=outputColumns)
这给出了
order typebc coil allocatedQuantity ton flag
0 o1 bct2 c1 12.000000 24.450000 0
1 o2 bct2 c2 11.340000 24.100000 0
2 o3 bct2 c2 9.460000 12.760000 0
3 o4 bct2 c1 6.540000 12.450000 0
4 o5 bct1 c3_1 5.693333 5.693333 1
5 o5 bct1 c3_2 5.693333 5.693333 1
6 o5 bct1 c3_3 5.693333 5.693333 1
7 o5 bct1 c4_1 5.680000 5.680000 1
8 o5 bct1 c4_2 5.680000 5.680000 1
9 o5 bct1 c4_3 5.680000 5.680000 1
10 o5 bct1 c5_1 5.676667 5.676667 1
11 o5 bct1 c5_2 5.676667 5.676667 1
12 o5 bct1 c5_3 5.676667 5.676667 1
13 o6 bct1 c6_1 5.670000 5.670000 1
14 o6 bct1 c6_2 5.670000 5.670000 1
15 o6 bct1 c6_3 5.670000 5.670000 1
16 o6 bct1 c7_1 5.660000 5.660000 1
17 o6 bct1 c7_2 5.660000 5.660000 1
18 o6 bct1 c7_3 5.660000 5.660000 1
19 o6 bct1 c8_1 5.660000 5.660000 1
20 o6 bct1 c8_2 5.660000 5.660000 1
21 o6 bct1 c8_3 5.660000 5.660000 1
22 o6 bct1 c9_1 0.030000 5.293333 1
23 o7 bct1 c9_1 3.962500 3.962500 1
...
44 o11 bct1 c14_1 4.745000 4.745000 1
45 o11 bct1 c14_2 4.745000 4.745000 1
46 o11 bct1 c13_1 3.897500 3.897500 1
47 o11 bct1 c13_2 3.897500 3.897500 1