Python/Pandas实现按条件分组和排名

3
我希望按邮政编码分组并生成包裹,但如果超过30000,应该再形成另一个包裹。我无法对其进行分组并排名。可能需要按重量升序排序以形成正确的包裹。非常感谢任何帮助。
我有以下数据:
   Load No.  Zip Code  Pounds    
     1         50507    20000 
     2         50507    8000
     3         50507    5000 
     4         60001    28000
     5         60001    30000
     6         60001    2000
     7         60001    4000
     8         60002    20000
     9         60002    18000
     10        60002    13000

输出:

Load No.     Zip Code  Pounds    Truck   Total Weight
     1         50507    20000     1         28000
     2         50507    8000      1         28000
     3         50507    5000      2         5000
     4         60001    28000     3         30000
     5         60001    30000     5         2000
     6         60001    2000      3         30000
     7         60001    4000      4         4000
     8         60002    20000     6         20000
     9         60002    18000     7         18000
     10        60002    13000     8         13000

我已经对数据框进行了排序: data=data.sort_values(by=['邮编','磅数'])

我也尝试按邮编分组,但是没有成功地加入条件(>20000)来形成密集排名: data['总重量'] = data.groupby('邮编')['磅数'].transform(sum)


欢迎来到Stackoverflow,请发布一个代码片段展示你的代码和你所尝试过的内容。 - Sashi
我已经添加了我的代码,但是我不知道如何通过分组来求和并制作卡车。非常感谢您的帮助。谢谢! - PyDataLov
1个回答

0

我想我明白你想要实现什么,所以我完成了你需要的部分,并留下其余部分让你自己决定。这个问题中最困难的部分似乎是智能地分配负载以最大化卡车空间。拆分物品并不是问题,但它并不像只需检查负载是否小于30,000那么简单。

首先,需要一种方法来智能地将负载分配到卡车上:

def build_trucks(sorted_loads):

    load_copy = np.array(sorted_loads)

    truck_max = 30000

    # check if any loads are > truck_max and split them into bins that sum to the load

    while len(load_copy) > 0:

        truck = []
        truck_load = 0

        for i, load in enumerate(load_copy):
            if truck_load + load <= truck_max:
                truck.append(i)
                truck_load += load

        yield load_copy[truck]

        load_copy = np.delete(load_copy, truck)

您没有提到是否有任何负载会超过30,000,所以我把它留下了。这本身就是一个有趣的问题(将45,000分成两个负载:30,000和15,000,将65,000分成两个30,000和一个5,000)。我对此进行了几次测试,包括您提供的测试:

print(list(build_trucks(np.array([20000, 8000, 5000]))))
print(list(build_trucks(np.array([30000, 28000, 4000, 2000]))))
print(list(build_trucks(np.array([20000, 18000, 13000]))))

print(list(build_trucks(sorted(np.array([25000, 1000, 1000, 4000, 5500]), reverse=True))))

输出结果为:

[array([20000,  8000]), array([5000])]
[array([30000]), array([28000,  2000]), array([4000])]
[array([20000]), array([18000]), array([13000])]
[array([25000,  4000,  1000]), array([5500, 1000])]

为了观察其行为,我运行了以下代码:
grp = data.groupby('zip')

for i, g in grp:
    print(g.sort_values('pounds', ascending=False))
    print()
    print(list(build_trucks(g['pounds'])))
    print()

其中 data 是您提供的原始数据的 DataFrame。希望问题的剩余部分对您而言变得明显。如果不是,请随时问我,我会尽力帮助(我留下了很多不完整的内容,因为这是一个很好的学习问题,但我不想花太多时间在上面)。可能有许多方法可以完成此操作,这是我看到的第一种方法。我还想到了一种递归的方法来做到这一点。其中任何一种都可能有效,也可能无效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接