Есть ли лучший способ выполнить инвентаризацию, используя Python? - PullRequest
0 голосов
/ 11 апреля 2020

Мы должны сделать что-то хаки sh в качестве лейкопластыря во время COVID. Мне дали список инвентаря для одного из наших меньших узлов корабля - он состоит приблизительно из 2 тысяч строк двух столбцов; SKU (уникальный идентификатор товара; int) и количество (сколько товаров на складе). Я также вытягиваю (через SQL) все заказы за последние несколько дней. Это более 400 тыс. Строк ORDR_NBR и SKU; ORDR_NBR соответствует 1-4 SKU. Задача, таким образом, состоит в том, чтобы выяснить, сколько «готовых к отправке» заказов узел мог бы выполнить в рабочем состоянии.

Мой нынешний подход использует Pandas; с фреймами данных 'df' (индекс отсортированных данных заказа - номер заказа) и inv_df '(отсортированный данные инвентаря, уникальный индекс - SKU):

output = [ordr_nbr for ordr_nbr in df.index.unique() if 
              (df[df.index == ordr_nbr].SKU.isin(inv_df.index)).sum() ==
              len(df[df.index == ordr_nbr])]

(наряду с некоторыми последующими шагами для вычитания инвентаря подсчитывает и исключает некоторые заказы с помощью распродажи)

Несмотря на то, что задача сложна в вычислительном отношении, время выполнения для указанной выше строки (3+ часа для сопоставления 400k: 2k на корпоративном ноутбуке) кажется чрезмерным. Да, Python является медленным языком, но это все, что у меня есть в данный момент.

ОБРАЗЦЫ ДАННЫХ:

df: {Индекс (порядковый номер): '002348579', SKU : 29483820, ORDR_DT: 2020-03-29 T12: 00}

inv_df: {Index (SKU): 29483820, QTY: 47}

ВЫХОД: (для строки выше)

002348579 '; поскольку в инвентаризационном_диске указан уникальный номер SKU, указанный выше, он может отправить весь заказ.

1 Ответ

0 голосов
/ 11 апреля 2020

Вот мое предложение:

# First I recreate a similar structure for the DataFrames
df = pd.DataFrame({"ORD_NB" : ['002348579', '002348579', '002348578', '002348578'],
                   "SKU" : ["29483820", "29483820", "29483825", "29483827"],
                   "ORDR_DT": pd.date_range("2020-03-29", periods=4)}).set_index("ORD_NB")
inv_df = pd.DataFrame({"SKU" : ["29483820", "29483825"],
                       "QTY" : [47, 45]}).set_index("SKU")

Фреймы данных выглядят так:

# df 
               SKU    ORDR_DT
ORD_NB                        
002348579  29483820 2020-03-29
002348579  29483820 2020-03-30
002348578  29483825 2020-03-31
002348578  29483827 2020-04-01
# inv_df
          QTY
SKU          
29483820   47
29483825   45

Поэтому нам нужен номер заказа 002348578, для которого SKU появляется в обоих df и inv_df, для того же числа наблюдений:

# I groupby ORD_NB and SKU in the first dataframe 
df = df.groupby(["ORD_NB", "SKU"]).agg({"SKU" : "count"}).rename(columns={"SKU":"count1"})
# I groupby SKU in second DataFrame
inv_df = inv_df.groupby("SKU").count().rename(columns={"QTY":"count2"})

# Then I merge the two dataframe (inner join)
output = pd.concat([df.reset_index().set_index("SKU"), inv_df], join="inner", axis=1)

# I only keep those for which the number of distinct SKU for each order number is
# the same in both DataFrames
output = output.loc[output["count1"]==output["count2"],:]

# I reset the index and drop unnecessary columns
output = output.reset_index().drop(columns=["count1", "count2", "SKU"])

Поэтому мой вывод:

     ORD_NB
0  002348578

Я думаю использовать groupby и concat вместо for l oop увеличит скорость.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...