Реализация Python/Pandas для группировки с условием и ранжированием
Я хочу сгруппировать по почтовому индексу и сформировать складки, но если он наберет 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 (по =['Почтовый индекс','Фунты'])
Также попытался сгруппировать по почтовому индексу, но не смог вставить условие (>20000) для формирования плотного ранга: data['Total weight'] = data.groupby('Zip Code')['Pounds']. Transform(sum)
1 ответ
Я думаю, что вижу, чего вы пытаетесь достичь, поэтому я завершил часть того, что вы ищете, а оставляю остальное, чтобы вы сами определились. Кажется, что самой сложной частью этой проблемы является разумное распределение нагрузки, чтобы максимизировать пространство для грузовика. Разделить вещи не проблема, но это не так просто, как просто проверить, если нагрузка меньше 30000.
Во-первых, метод интеллектуального распределения нагрузок между грузовыми автомобилями:
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)
Вы не упомянули, начнутся ли какие-либо нагрузки как более 30000, поэтому я ушел, но не незавершенным. Это само по себе было бы интересной проблемой (разбить 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 исходных данных, которые вы предоставили. Надеемся, что остальная часть проблемы станет очевидной для вас. Если нет, не стесняйтесь спрашивать, и я сделаю все возможное, чтобы помочь (я оставил многое из этого неполным, потому что это большая проблема для вас, однако я не хотел тратить на это слишком много своего собственного времени). Вероятно, есть много способов сделать это, это первый способ, который я увидел. Я также подумал о рекурсивном способе сделать это. Может быть, а может и не быть эффективным.