wangxishi

2020-11-17   阅读量: 11303

Python大数据

用python解决装箱问题

需实现:

1,要把左边的18笔金额,装入右边的三个金额包内,金额包要求的下限必须达到,上限可以不达到,只要不超过上限金额就行

2,要满足最大装箱原则(其实就是左边每笔匹配到右边的金额包中,按照尽量合理的方式匹配)

3,提供一种用excel的思路,用excel就是先把待装箱的18笔金额降序排序,然后从上往下拉,每个金额包的金额快放满的时候,再塞进去一些排序靠后的金额小的几笔,只要每个金额包总金额大于金额包下限且不超过金额包的上限就行

4,不想用excel的原因是原始数据上千笔,手工操作非常麻烦,想用python实现

谢谢!

金额包.xlsx

待装箱清单.xlsx

image.png

添加CDA认证专家【维克多阿涛】,微信号:【cdashijiazhuang】,提供数据分析指导及CDA考试秘籍。已助千人通过CDA数字化人才认证。欢迎交流,共同成长!
28.9030 2 18 关注作者 收藏

评论(18)

ermutuxia
2021-01-20
box.sort_values(by=["箱子是否达下限","为达下限还需要补充"],ascending=[True,False],inplace=True)

这一句是对数据框box进行排序,按照字段“箱子是否达上限”,“为达下限还需要补充”;两个字段分别按升序,降序排

0.0000 0 0 回复
wangxishi
2021-01-19

哪句是对数据框进行排序呢?

55.7549 1 0 回复
ermutuxia
2021-01-19

每次循环的时候数据框都会进行排序,所以虽然位置(一直未第一行)没有变,但是对应的值是可能改变的。

0.0000 0 0 回复
wangxishi
2021-01-19

这里面的loc[0,"当前金额"]的0 会随着每次循环,0会变化是吗

image.png

149.9154 1 0 回复
ermutuxia
2020-12-10

这是把第i个订单的装箱编号找出来,这样我们就知道每笔订单装到了哪个箱子里面了

0.0000 0 0 回复
wangxishi
2020-12-10

waitbox.loc[i,"装箱编号"]=box["ID"][0]

这步是什么作用呢

133.3258 1 0 回复
ermutuxia
2020-12-09

一个订单一个订单的分配,i表示第几个订单,分配完一个订单就分配下一个订单,直到所有订单都分配完,因为用的是while语句,要自己进行i=i+1操作

0.0000 0 0 回复
wangxishi
2020-12-09

这个是怎么判定循环到所有的待分配金额的,最后一行i=i+1是什么意思?

133.3258 1 0 回复
ermutuxia
2020-11-18

image.png

0.0000 0 0 回复
ermutuxia
2020-11-18
#导入库
import pandas as pd
#导入数据生成数据框
box=pd.read_excel("D:\\360安全浏览器下载\\金额包.xlsx",skiprows=0,usecols=[0,1,3,4,5])
waitbox=pd.read_excel("D:\\360安全浏览器下载\\待装箱清单.xlsx",skiprows=0,usecols=[0,1])
#waitbox为等待被分箱的数据


#对数据框waitbox,按照金额从到小的顺序进行排序
waitbox.sort_values(by="金额",ascending=False,inplace=True)
#重设数据框waitbox索引
waitbox.reset_index(inplace=True)
#准备waitbox的相关指标
waitbox["装箱编号"]=""

#准备box的相关指标
box["当前金额"]=0
box["剩余空间"]=box["上限"]-box["当前金额"]
box["为达下限还需要补充"]=box["下限"]-box["当前金额"]
box["订单集和"]=box["ID"].map(lambda x:list())
box["箱子是否达下限"]=False
#将箱子按照箱子上限进行排序,升序排列
box.sort_values(by="为达下限还需要补充",ascending=False,inplace=True)




#然后对每笔订单进行箱子分配
rows=waitbox.shape[0]
i=0   #用i表示第几个订单
while i<rows:
    print("现在对第%d个订单进行分配"%i,end="")


    #检验第i个物品是否可以放在根据"为达下限还需要补充"降序排序的第一个箱子

    if box.loc[0,"剩余空间"]>waitbox.loc[i,"金额"]:
        print(box.loc[0,"ID"])
        box.loc[0,"当前金额"]=box.loc[0,"当前金额"]+waitbox.loc[i,"金额"]
        box.loc[0,"剩余空间"]=box.loc[0,"上限"]-box.loc[0,"当前金额"]
        box.loc[0,"为达下限还需要补充"]=box.loc[0,"下限"]-box.loc[0,"当前金额"]
        waitbox.loc[i,"装箱编号"]=box["ID"][0]
        新增物品=(waitbox.loc[i,"ID"],waitbox.loc[i,"金额"])
        box["订单集和"][0]=box["订单集和"][0]+[新增物品]
        if box.loc[0,"当前金额"]>=box.loc[0,"下限"]:
            box.loc[0,"箱子是否达下限"]=True
        #对各个箱子的剩余容量进行排序
        box.sort_values(by=["箱子是否达下限","为达下限还需要补充"],ascending=[True,False],inplace=True)
        box.reset_index(inplace=True,drop=True)
        
    else:
        print("第%d个物品没有办法再装了"%i,"金额为",waitbox.loc[i,"金额"],"准备装箱代码为",box.loc[0,"ID"],sep="")
        break
    
    
    i=i+1
    



box.to_excel("D:\\分箱后每个箱子的情况.xlsx")
waitbox.to_excel("D:\\每笔订单分箱结果.xlsx")


0.0000 0 0 回复
wangxishi
2020-11-18

金额包下限和上限在文件中已提供,要大于等于下限,不超过上限即可

0.0000 0 0 回复
ermutuxia
2020-11-18

金额包的上下限没有提供image.png

0.0000 0 0 回复
wangxishi
2020-11-18

我增加了数据,两个文件分别是待装箱清单和金额包,这个是肯定能匹配出来的,用excel手工可以操作,看看用代码是否可以实现?每个金额包下限及上线定义都是一样的

0.0000 0 0 回复
ermutuxia
2020-11-18

我查阅了一些资料,这个问题还真是挺复杂的,没查到专门针对这个问题的算法,因为这个问题要求箱子必须达到下限不能超过上限,不一定有解。但是我觉得这个问题特别有意义。你现在个问题,现有箱子一旦装不了,我可以决定换箱子吗。你给我的是三种规格20000,25000,30000的箱子分别一个共3个,我可以变成25000规格的箱子两个,2000规格的箱子一个吗,就是类似的这种替换可以吗。

0.0000 0 0 回复
wangxishi
2020-11-17

对 金额包的个数和上限下限都是设定好了的 只要能把左边的每笔装进去 并符合上下限要求就行

0.0000 0 0 回复
ermutuxia
2020-11-17

好的,收到。然后我再问一个问题呀,就是右边的金额包个数以及金额包的上下线都是提前设定好的吗

0.0000 0 0 回复
wangxishi
2020-11-17

这两列ID不匹配,左边的待装箱笔数和右边的金额包其实是两张表,两张表匹配方式跟ID 没有关系,就是左边的多笔金额分笔数装入右边的金额包中,每个金额包要符合总金额大于等于每个金额包的下限并且小于金额包的上限就行,左边的每笔金额只能选择右边一个金额包装入不能重复装入两个金额包,最后右边3个金额包里面的笔数之和应该正好等于左边的金额笔数,就是16笔

65.7297 1 0 回复
ermutuxia
2020-11-17

我看你截图里面的两列id的取值是不一样,比如截图中第一个表id取值为HJ...,而截图右边的表id只是几个数字,这两列id是一个意思吗

0.0000 0 0 回复

推荐课程