#python-3.x #pandas #stringio
#python-3.x #pandas #stringio
Вопрос:
У меня есть список заказов с отдельной системой инвентаризации (Google Sheets). Используя Pandas, я пытаюсь объединить их для эффективного «списка выбора» и добился некоторого умеренного успеха. Однако при тестировании (добавление нескольких количеств для заказа, наличие нескольких заказов с одним и тем же типом товара / артикула) он начинает ломаться.
orders = "orderNumber,SKU,Quantityrn11111,GreenSneakers,2rn11111,Brown_Handbag,1rn22222,GreenSneakers,1rn33333,Blue_Handbag,1"
str_orders = StringIO(orders, newline='n')
df_orders = pd.read_csv(str_orders, sep=",")
inventory = "SKU,LocationrnGreenSneakers,DA13ArnGreenSneakers,DA13ArnRed_Handbag,DA12ArnGreenSneakers,DB34CrnGreenSneakers,DB33Crn"
str_inventory = StringIO(inventory, newline='n')
df_inventory = pd.read_csv(str_inventory, sep=",")
df_inventory = df_inventory.sort_values(by='Location', ascending=False)
df_pList = df_orders.merge(df_inventory.drop_duplicates(subset=['SKU']), on='SKU', how='left')
print(df_pList)
псевдожелаемый результат:
'
orderNumber, SKU, Quantity, Location
11111, GreenSneakers, 1, DB34C
11111, GreenSneakers, 1, DB33C
11111, Brown_Handbag, 1, NA
22222, GreenSneakers, 1, DA13A
33333, Blue_Handbag, 1, NA
'
Является ли слияние вообще способом решения проблемы такого типа? По возможности стараясь избегать зацикливания.
Ответ №1:
Ниже приведены три фрейма данных.
df_pickList
это то, что вы просили сделать
copy_inventory
содержит, каким будет инвентарь, если вы выберете все (на случай, если вы захотите просто записать фрейм данных, чтобы перезаписать свой файл инвентаря) Вы могли бы отказаться от копирования и использовать свой df_inventory
напрямую, но особенно в бета-версии удобно создавать копию для манипуляций.
df_outOfStock
это удобная корзина для сбора вещей, которых у вас нет в инвентаре. Сверьте текущие заказы, чтобы увидеть, что вам нужно получить в заказе
from io import StringIO
import pandas as pd
import copy
orders = """orderNumber,SKU,Quantity
11111,GreenSneakers,2
11111,Brown_Handbag,1
22222,GreenSneakers,1
33333,Blue_Handbag,1
"""
str_orders = StringIO(orders, newline='n')
df_orders = pd.read_csv(str_orders, sep=",")
inventory = """SKU,Location
GreenSneakers,DA13A
GreenSneakers,DA13A
Red_Handbag,DA12A
GreenSneakers,DB34C
GreenSneakers,DB33C
"""
str_inventory = StringIO(inventory, newline='n')
df_inventory = pd.read_csv(str_inventory, sep=",")
df_inventory = df_inventory.sort_values(by='Location', ascending=False)
df_outOfStock = pd.DataFrame() #placeholder to report a lack of stock
df_pickList = pd.DataFrame() #placeholder to make pick list
copy_inventory = copy.deepcopy(df_inventory) #make a copy of inventory to decimate
for orderIndex, orderLineItem in df_orders.iterrows():
for repeat in range(orderLineItem["Quantity"]): #since inventory location is 1 row per item, we need to do that many picks per order line item
availableInventory = copy_inventory.loc[copy_inventory.loc[:,"SKU"] == orderLineItem["SKU"], :]
if len(availableInventory) == 0:
#Failed to find any SKU to pull
df_outOfStock = df_outOfStock.append(orderLineItem, ignore_index=True)
else:
pickRow = {"orderNumber": orderLineItem["orderNumber"],
"SKU": orderLineItem["SKU"],
"Quantity": 1,
"Location": availableInventory.iloc[0]["Location"]}
df_pickList = df_pickList.append(pickRow, ignore_index=True)
copy_inventory.drop(index = availableInventory.index[0], inplace=True)
Спасибо, это было забавное упражнение по сравнению с работой с нецелыми количествами (например, футами углового железа)
(Оригинальный неправильный ответ ниже)
Я бы рекомендовал объединить строки в одну таблицу (не объединять и / или перезаписывать значения), затем использовать group by, чтобы разрешить агрегирование значений.
В качестве примера я бы начал с этих двух ссылок по объединению ваших данных:
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html#pandas.concat
Комментарии:
1. На работе я просмотрел ваш вопрос и подумал, что хорошо понимаю, чего вы пытались достичь, но теперь, когда я вернулся домой, я думаю, что ошибался. не могли бы вы, пожалуйста, обновить свой первоначальный вопрос, чтобы включить желаемый результат из примера кода. Я бы прокомментировал ваш вопрос, чтобы задать его вам, но у меня недостаточно репутации, чтобы комментировать что-либо, кроме моего ответа.
2. Абсолютно я могу. В данный момент я не на своем главном компьютере, так что, надеюсь, «псевдовыход» поможет
3. Есть причина, по которой вы хотите избежать зацикливания? Мне нужно немного обдумать это, чтобы придумать решение, которое не зацикливается. До тех пор я рекомендую вам разбить свой код, чтобы узнать, что происходит.
df_inventory.drop_duplicates(subset=['SKU'])
сначала это происходит в вашем большом однострочнике. Для облегчения понимания разбейте его на две строки:temp = df_inventory.drop_duplicates(subset=['SKU'])
иdf_pList = df_orders.merge(temp, on='SKU', how='left')
. Затем вы можете распечатать,temp
чтобы увидеть, с чемmerge
пытаются работать.4. Спасибо, я вижу, что drop_duplicates — это не то, что я ищу. Есть ли способ объединить списки и заставить левый (список заказов) присоединяться к каждому последующему совпадению инвентаря без дублирования?
5. При циклировании я думал, что это может замедлиться из-за тысяч строк инвентаря. Здесь я тоже могу быть невежественным.