熊猫数据框:订单供应匹配

时间:2020-06-21 22:06:59

标签: python pandas dataframe apache-spark-sql stack

我对python或pandas编码非常陌生。所以我有点惊讶,任何输入都值得赞赏。 我有两个df,根据条件分别订购。 df1:带数量的订单清单 df2:具有可用数量和日期的库存清单。数量不一定等于订单数量。

我需要在df1中弹出第一笔订单,并在df2中继续弹出库存,直到满足订单数量并维护执行订单所需的库存数量

任何帮助将不胜感激

Example 

df 1: 
order1 5
order2 4
order3 5

df 2: inventories 
inven1 7 07/06/2020
inven2 7 07/10/2020

my final output should look like this.

inven1 | 5 | 07/06/2020 | order1 
inven1 | 2 | 07/06/2020 | order2 
inven2 | 2 | 07/10/2020 | order2
inven2 | 5 | 07/10/2020 | order3 

@伊恩 感谢您的回答,它工作得非常好,我唯一的问题是,这些库存和订单必须基于metaID进行匹配,metaId中的库存应应用于相同metaID的订单。

我尝试遍历metaID并执行订单库存匹配,如下所示。我得到了想要的结果,但是最大的问题是,仅2K行的数据大小需要20分钟。

我尝试通过按metaID对订单和库存进行排序并传递整个数据框来解决该问题。当订单和库存具有完全匹配的数量时,它就可以使用

df 1: 
metaId1 order1 5
metaId1 order2 4
metaId1 order3 5
metaId2 order4 10

df 2: inventories 
metaId1 inven1 7 07/06/2020
metaId1 inven2 7 07/10/2020
metaId2 inven3 10 07/10/2020

my final output is all fine.

metaId1 | inven1 | 5 | 07/06/2020 | order1 
metaId1 | inven1 | 2 | 07/06/2020 | order2 
meatId1 | inven2 | 2 | 07/10/2020 | order2
metaId1 | inven2 | 5 | 07/10/2020 | order3 
metaId2 | inven3 | 10 | 07/10/2020 | order4 

但是当库存过多或短缺时,就会发生metaId之间的交叉,这是因为我们基于索引进行匹配。如何根据metaId进行匹配,然后根据内部索引进行匹配。我拥有的for循环解决方案永远需要处理大量数据,我知道那不是正确的解决方案。每个metaId下的这些顺序匹配可以并行发生,并且可以合并结果。那是我用for循环来做的。我不知道如何在python / pandas中并行化它们,或者不存在比并行计算更好的解决方案。似乎我需要应用groupBy-appLy-combine概念,但是我看到了具有单个数据帧的该概念的示例,并对该行应用了一些逻辑,然后将其组合。我的问题是,我有两个数据框,必须进行分组并将“ combine-first()”解决方案应用于该组,并合并每个组的结果。我不确定该怎么做。你能帮我这个忙吗?

current problem 

df 1: 
metaId1 order1 5
metaId1 order2 4
metaId1 order3 5
metaId2 order4 10

df 2: inventories 
metaId1 inven1 7 07/06/2020
metaId1 inven2 5 07/10/2020
metaId2 inven3 10 07/10/2020


final output : --> not right 

metaId1 | inven1 | 5 | 07/06/2020 | order1 
metaId1 | inven1 | 2 | 07/06/2020 | order2 
meatId1 | inven2 | 2 | 07/10/2020 | order2
metaId1 | inven2 | 3 | 07/10/2020 | order3 
metaId2 | inven3 | 2 | 07/10/2020 | order3 -->crossover
metaId2 | inven3 | 8 | 07/10/2020 | order4

expected output : 
metaId1 | inven1 | 5 | 07/06/2020 | order1 
metaId1 | inven1 | 2 | 07/06/2020 | order2 
meatId1 | inven2 | 2 | 07/10/2020 | order2
metaId1 | inven2 | 3 | 07/10/2020 | order3 
metaId1 | short  | 2 | 07/10/2020 | order3-->short by 2 inven to fulfill order
metaId2 | inven3 | 10 | 07/10/2020 | order4

1 个答案:

答案 0 :(得分:0)

创建df1:

从顺序1 = 5,在一行中创建5个[顺序1,顺序1,顺序1,顺序1,顺序1]的Elmenet。与订单2和订单3相同

import pandas as pd

df1 = pd.DataFrame({'Order Number':['order 1','order 2','order 3'],
              'Quantity':[5,4,3]})

df1 = df1.set_index('Order Number')
df1  = df1.loc[df1.index.repeat(df1['Quantity'])]
df1

创建df2:

从inven1 = 7,在一行中创建[inven1,inven1,inven1,inven1,inven1,inven1]的7个元素。与inven2一样

df2  = pd.DataFrame({'Batch':['inven1','inven2','inven3'],
                    'Quantity':[7,4,10],
                    'Date Available':['2020-07-06','2020-07-10','2020-07-12']
                    })

df2 = df2.set_index('Date Available')
df2 = df2.loc[df2.index.repeat(df2['Quantity'])]
df2

创建df3:

将所有订单放在一列中,将所有inven1放在另一列中以使它们一对一匹配。

请确保替换“订单”下的NA,以确定哪些库存没有匹配的订单号。

df3 = df1.reset_index().combine_first(df2.reset_index()).reset_index()
#Make sure to replace NAs with "Available Stock"
df3['Order Number']  = df3['Order Number'].fillna('Available Stock')
df3

创建df4:

使用groupby创建一个数据透视表,其中显示了由库存填写的每个订单的计数。

df4 = df3.groupby(['Batch','Date Available','Order Number']).count().reset_index().drop(labels = ['index'], axis = 1)
df4

结果应显示:

    Batch   Date Available  Order Number       Quantity
0   inven1  2020-07-06      order 1            5
1   inven1  2020-07-06      order 2            2
2   inven2  2020-07-10      order 2            2
3   inven2  2020-07-10      order 3            2
4   inven3  2020-07-12      Available Stock    9
5   inven3  2020-07-12      order 3            1

来源:

  1. Concatenate two dataframes of different sizes (pandas)
  2. Repeat rows in a pandas DataFrame based on column value