如何从另一个数据帧中获取适当的类别 - 一对多匹配

How to get Appropriate category from another dataframe - one to many match

提问人:ghost_like 提问时间:3/9/2023 更新时间:3/9/2023 访问量:57

问:

我们有**两台机器**,每台机器生产的数量不一致DF1 是它的 DataFrame

df1 = pd.DataFrame({'machine':['A','A','A','A','A','B','B','B','B','B','B'],'qty':[1,3,5,2,4,2,4,5,5,3,2]})

[df1]

df2 是 DataFrame 的箱体体积大小,每个体积大小也不同

df2 = pd.DataFrame({'machine':['A','A','A','A','A','B','B','B','B','B','B','B'],
                    'box_id':['box_1','box_2','box_3','box_4','box_5','box_6','box_7','box_8','box_9','box_10','box_11','box_12'],
                    'volume':[4,5,3,2,5,3,4,3,6,4,8,5]})

[df2]

我想将“box_id”列添加到 df1 中,以查找并匹配df2 的专有框 ID。 就像底部的输出数据帧一样。

output_df = pd.DataFrame({'machine':['A','A','A','A','A','B','B','B','B','B','B'],
                           'qty':[1,3,5,2,4,2,4,5,5,3,2],
                           'box_id':['box_1','box_1','box_2','box_3','box_5','box_6','box_7','box_9','box_11','box_12','box_12']})

[output_df]

详细解释

按从上到下顺序添加box_id以**接近每个箱子的体积**(DF2),但不要超过每个箱子

例如 在机器 A 中,第一个产品数量为 1,但第一个盒子 (box_1) 体积为 4 box_1可以包含第一个产品,第一列中的框 ID 为box_1

然后第二个产品数量是3, box_1有第一个产品(数量 1),但该框中有 3 个可用空间 第二行中的框 ID 也box_1 ** 第三个产品是 5,下一个盒子(box_2)体积是 5,所以第三行是box_2第四个产品是 2,下一个盒子(box_3)体积是 3,所以第三行是box_3 ** 但在第五种情况下,乘积是 4,但下一个盒子(box_4)只有 2, 所以box_4不能使用,必须使用以下box_5 ** 当机器更换时,请再次重置盒子并使用下一个盒子。

在机器 B 中,第一个产品数量为 2,但下一个盒子(box_6)体积为 3 所以可以使用box_6

不是为了学习,它实际上是在我们工厂生产的。 我将用它进行部分自动化

我希望能得到专家的很多帮助

Python 熊猫 匹配

评论


答:

1赞 rajendra 3/9/2023 #1

您可以通过简单地逐行迭代 df1 并将每个项目放在存储在列表中的框中来以更直接的方式执行此操作。但我想探索如何更有效地做到这一点,特别是如果盒子可以非常大并且可以容纳大量物品。

所以,我们开始吧。

您可以先向 df1 添加累积总和列。

    df1['cum_sum'] = df1.groupby('machine').cumsum()

然后,您可以遍历 df2 中的框,并将 df1 中的尽可能多的项目放入框中,然后移动到下一个框。如果没有物品适合盒子,你就不要在里面放任何东西,然后移动到下一个盒子。您可以跟踪已放置的物品的累积数量,以便仅查找尚未放置的物品。


    for machine, df in df2.groupby('machine'):
      cum_volume_placed = 0
      for indx, row in df.iterrows():
        applicable_rows = df1['machine'] == machine  # all items in this machine
        applicable_rows &= df1['cum_sum'] > cum_volume_placed  # which are after whatever we already placed
        applicable_rows &= df1['cum_sum'] <= cum_volume_placed + row.volume  # which fits within current box
        if sum(applicable_rows) > 0:
          df1.loc[applicable_rows, 'box_id'] = row.box_id
          cum_volume_placed = df1.loc[applicable_rows, 'cum_sum'].iloc[-1]

评论

1赞 ghost_like 3/10/2023
美妙!!!!!!!!!!。你做得比我预期的要好。非常感谢