admin管理员组

文章数量:1336633

I have a dataframe question. I have two dataframes. 1st dataframe contains orders details and 2nd dataframe contains coil details. I need to assign orders to coils to satisfy the demand of the orders. Every orders have a minimum and maximum coil weight range, so when allocating the orders, I need to maintain the minimum and maximum tons. For example, say an order has a demand of 14 and min and max range is 10 and 14 respectively, the available coil weight is 24, then I need to divide the 24 tons coils into two parts, 12 each and then from one 12, I'll assign 12 and then from 2nd 12, I'll assign 2 to satisfy the demand of 14. My 1st dataframe (order denotes unique order ids) is

     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

2nd datafarme (mc denotes unique coil number) is

     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

To address parting, I have defined a function. I have written the code, but allocation is not coming right. Also note that, we can satisfy more than the demand (10% extra) to utilize a coil fully. My code is below

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)

Pls help.

I have a dataframe question. I have two dataframes. 1st dataframe contains orders details and 2nd dataframe contains coil details. I need to assign orders to coils to satisfy the demand of the orders. Every orders have a minimum and maximum coil weight range, so when allocating the orders, I need to maintain the minimum and maximum tons. For example, say an order has a demand of 14 and min and max range is 10 and 14 respectively, the available coil weight is 24, then I need to divide the 24 tons coils into two parts, 12 each and then from one 12, I'll assign 12 and then from 2nd 12, I'll assign 2 to satisfy the demand of 14. My 1st dataframe (order denotes unique order ids) is

     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

2nd datafarme (mc denotes unique coil number) is

     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

To address parting, I have defined a function. I have written the code, but allocation is not coming right. Also note that, we can satisfy more than the demand (10% extra) to utilize a coil fully. My code is below

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)

Pls help.

Share asked Nov 19, 2024 at 20:09 MangluManglu 2662 silver badges11 bronze badges 2
  • 1 can you provide an example of what you mean? – iBeMeltin Commented Nov 19, 2024 at 20:23
  • I am allocating orders to the coils considering the order min and max weight. – Manglu Commented Nov 20, 2024 at 2:43
Add a comment  | 

1 Answer 1

Reset to default 0

The issue is in the splitting and allocation logic. You can solve this by improving the splitNumber function to return the correct number of parts within the specified min-max range. It updates the main allocation loop to handle scenarios in which coils are split across multiple orders while still meeting the 10% overage limit. I would suggest doing this:

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)

which gives

   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

本文标签: pandasAllocating orders to resources joining two python dataframeStack Overflow