【问题标题】:Comparing three data frames to evaluate multiple criteria比较三个数据框以评估多个标准
【发布时间】:2023-01-25 01:24:11
【问题描述】:

我有三个数据框:

  • ob (Orderbook) - 包含零件号、到期周和构建它们所需的时间的订单簿。

    Part Number Due Week Build Hours
    A 2022-46 4
    A 2022-46 5
    B 2022-46 8
    C 2022-47 1.6
  • osm(操作员技能矩阵)——包含操作员姓名和零件号的技能矩阵

    Operator Part number
    Mr.One A
    Mr.One B
    Mr.Two A
    Mr.Two B
    Mrs. Three C
  • ah(可用时间)- 包含操作员在给定一周内可以工作多少小时的列表

    Operator YYYYWW Hours
    Mr.One 2022-45 40
    Mr.One 2022-46 35
    Mr.Two 2022-46 37
    Mr.Two 2022-47 39
    Mrs. Three 2022-47 40
    Mrs. Three 2022-48 45

我正在尝试每周计算是否有足够多的操作员、具备合适的技能、工作时间足以完成订单簿上的所有订单。如果没有,请确定无法完成的订单。

一步一步看起来像这样:

  1. 取订单簿第一行的零件号。
  2. 搜索技能矩阵以查找可以构建该零件的操作员列表。
  3. 搜索营业时间列表并检查操作员在订单到期的那一周是否有可用的房屋。
  4. 如果操作员有可用时间,请将他们的名字添加到订单簿的那一行。
  5. 从 Avalible Hours df 中的 Available hours 中减去 orderbook 中的 Build hours。
  6. 对订单簿中的每一行重复此操作,直到所有订单都有对应的名称或没有剩余可用时间。

    我唯一想尝试的是一堆嵌套的 for 循环,但是由于有数千行,完成一次迭代需要大约 45 分钟,并且需要几天甚至几周才能完成整个事情。

    #for each row in the orderbook
    for i, rowi in ob_sum_hours.iterrows():
        #for each row in the operator skill matrix
        for j, rowj in osm.iterrows():
            #for each row in the avalible operator hours
            for y, rowy in aoh.iterrows():
                if(rowi['Material']==rowj['MATERIAL'] and rowi['ProdYYYYWW']==rowy['YYYYWW'] and rowj['Operator']==rowy['Operator'] and rowy['Hours'] > 0):`
            rowy['Hours'] -=rowi['PlanHrs']
            rowi['HoursAllocated'] = rowi['Operator']
        
    

    最终结果如下所示:

    Part Number Due Week Build Hours Operator
    A 2022-46 4 Mr.One
    A 2022-46 5 Mr.One
    B 2022-46 8 Mr.Two
    C 2022-47 1.6 Mrs.Three

    有没有更好的方法来实现这一目标?

【问题讨论】:

  • 为什么一先生和二先生分配到预期输出的前三行?在 ah dataframe 中,它们没有在到期周(2022-46)中列出?另外,二先生不能按照osm框架搭建Part C。
  • 只是想问同样的问题。一般而言,第 46 周根本不会出现在 ah 中,这是由于不好的例子,还是只有几周没有操作员可用。
  • 基于所有的框架,我相信预期的输出应该是C,2022-47,1.6,Mrs. Three
  • 对不起,不好的例子,我已经更新了它以使其更清楚。
  • @jhew123 感谢更新,但二先生无法构建 C 部分。为什么二先生在 C 部分的预期输出中?

标签: python pandas dataframe


【解决方案1】:

用一个循环制作 + 在每一行上应用。

Orderbook.groupby(Orderbook.index) 按索引分组,即 my_func 遍历每一行,仍然比循环更好。

在 'aaa' 列表中,我们得到一个匹配的 unique 运算符列表。在“bbb”列表中,过滤可用条件:“YYYYWW”、“操作员”(使用 isin 作为唯一操作员列表)和大于 0 的“小时数”。进一步在循环中,使用“bbb”索引,我们检查空闲时间,如果 'ava' 大于零,则使用显式索引 loc 设置值。

import pandas as pd

Orderbook = pd.read_csv('Orderbook.csv', header=0)
Operator = pd.read_csv('Operator.csv', header=0)
Avaliable= pd.read_csv('Avaliable.csv', header=0)

Orderbook['Operator'] = 'no'


def my_func(x):
    aaa = Operator.loc[Operator['Part number'] == x['Part Number'].values[0], 'Operator'].unique()
    bbb = Avaliable[(Avaliable['YYYYWW'] == x['Due Week'].values[0]) &
                    (Avaliable['Operator'].isin(aaa)) & (Avaliable['Hours'] > 0)]

    for i in bbb.index:
        ava = Avaliable.loc[i, 'Hours'] - x['Build Hours'].values
        if ava >= 0:
            Avaliable.loc[i, 'Hours'] = ava
            Orderbook.loc[x.index, 'Operator'] = Avaliable.loc[i, 'Operator']
            break# added loop interrupt


Orderbook.groupby(Orderbook.index).apply(my_func)

print(Orderbook)
print(Avaliable)

更新 18.11.2022我没有循环就做到了。但是,你需要检查一下。如果您发现不正确的地方,请告诉我。您还可以通过在开头放置以下内容来测量确切的处理时间:

import datetime

now = datetime.datetime.now()

并在最后打印经过的时间:

time_ = datetime.datetime.now() - now
print('elapsed time', time_)

代码:

Orderbook = pd.read_csv('Orderbook.csv', header=0)
Operator = pd.read_csv('Operator.csv', header=0)
Avaliable = pd.read_csv('Avaliable.csv', header=0)

Orderbook['Operator'] = 'no'

aaa = [Operator.loc[Operator['Part number'] == Orderbook.loc[i, 'Part Number'], 'Operator'].unique() for i in
       range(len(Orderbook))]


def my_func(x):
    bbb = Avaliable[(Avaliable['YYYYWW'] == x['Due Week'].values[0]) &
                    (Avaliable['Operator'].isin(aaa[x.index[0]])) & (Avaliable['Hours'] > 0)]

    fff = Avaliable.loc[bbb.index, 'Hours'] - x['Build Hours'].values
    ind = fff[fff.ge(0)].index
    Avaliable.loc[ind[0], 'Hours'] = fff[ind[0]]
    Orderbook.loc[x.index, 'Operator'] = Avaliable.loc[ind[0], 'Operator']


Orderbook.groupby(Orderbook.index).apply(my_func)

print(Orderbook)
print(Avaliable)

【讨论】:

  • 谢谢,我已经用我的数据对此进行了测试,并且它完全按照需要工作。我认为它从上到下遍历 Orderbook 是否正确?因此,如果我想在未来对订单簿进行排名,我可以在运行此代码之前按另一列排序。
  • 是的,从订单簿的第一行开始一切都是正确的。您可以通过将 my_func 放入函数中来测试它:print('index', x.index, 'Operator', Orderbook.loc[x.index, 'Operator'].values)。该函数遍历每一行。我想知道整个计算进行了多长时间?
  • 谢谢。我在订单簿中运行了约 5000 行,在操作员中运行了约 12000 行,在可用行中运行了约 600 行,大约需要 30 秒才能完成。订单簿和可用数据集目前仅限于接下来的三周,但是,上线后将扩展到 20 周。
  • 不要离开。我找到了一些东西(这需要几分钟)。
  • 添加了中断休息循环,因为需要一个操作:if ava >= 0:.没有它,减法会发生多次。再检查一遍。检查方式:可用。
猜你喜欢
  • 1970-01-01
  • 2021-04-07
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-16
  • 2018-09-27
  • 2020-04-15
相关资源
最近更新 更多