0

好的,所以我需要帮助和/或建议如何解决材料树的准时/延迟问题。

我有一个熊猫数据框,其中包含材料树(['Tree'])、该树内的不同级别(['Level'])、零件编号(['Part #'])、预定的开始日期(['Sched Start' ])和预定的完成日期(['Sched Fin'])。

import pandas as pd


data = {'Tree': [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3],
        'Level': [1, 2, 2, 3, 1, 2, 3, 4, 1, 2, 3, 2, 3, 2],
        'Part #': ['11', '12A', '12B', '12B3',
                   '21', '22A', '22A3', '22A4',
                   '31', '32A', '32A3', '32B', '32B3', '32C'],
        'Sched Start': pd.to_datetime(['12/01/2020', '11/01/2020', '11/01/2020', '10/01/2020',
                        '12/01/2020', '11/01/2020', '10/01/2020', '09/01/2020',
                        '12/01/2020', '11/01/2020', '10/01/2020', '11/01/2020', '10/01/2020', '11/01/2020']),
        'Sched Fin': pd.to_datetime(['12/15/2020', '11/15/2020', '12/02/2020', '11/02/2020',
                        '12/15/2020', '11/15/2020', '11/02/2020', '09/15/2020',
                        '12/15/2020', '11/15/2020', '10/15/2020', '11/15/2020', '10/15/2020', '11/15/2020'])        
        }

df = pd. DataFrame(data)

正常的物料流是物料供给下一个更高的组件。例如,第 3 级项目馈入第 2 级项目。2 级项目为 1 级项目提供食物(1 级是不提供任何东西的顶部/最终组件)。可能有多个级别 2 馈送单个级别 1。多个级别 3 馈送单个级别 2 等等。所以在上面的示例代码中(对于树 1):12B3 馈送到 12B,12A 和 12B 馈送到 11。

无论如何,我需要添加另一列,其中包含一个项目的完成日期与其下一个更高装配的开始日期的比较数据。回到我们上面的例子。第 3 级部分 12B3 的完成日期为 2020 年 2 月 11 日 - 它提供了开始日期为 2020 年 11 月 1 日的 12B:12B3 是迟到的。查看日期,12B 会迟到,12A 会准时。

较低的组件将始终位于较高的组件之下。

像泥一样清澈,对吧?

我试过的:

好吧,我对遍历每一行的循环进行了一次可怕的尝试。如果前一行级别>当前行级别,它会获取级别值,然后转到下一行,它将当前行“Sched Fin”与前一行“Sched Start”进行比较,并取得了一点成功。当然,当序列中有相同级别的项目(例如两个级别 2)时,这一切都会爆炸。

任何帮助将不胜感激。

** 编辑 ** 树是相互独立的。不像关卡那样捆绑在一起。

4

1 回答 1

2

就像评论中提到的 above_c_level 一样,通过一两个类来跟踪喂养路径会更容易。

对于我的回答,我修改了您的data字典,以便在树级别和后续生产级别之间使用分号,以便可以更轻松地将它们相互比较(即'1;2B;3')。

首先,为您的各个零件开设的课程有助于跟踪不同零件之间的喂食情况。

class Part():
    def __init__(self, part, level, start, finish):
        self.part = part
        self.level = level
        self.start = pd.to_datetime(start)
        self.finish = pd.to_datetime(finish)
        self.feedsl = []
        self.isfedl = []
        self.status = None
    def __str__(self):
        return '({}, {}, {}, {})'.format(self.part, self.level, self.start, self.finish)
    def __repr__(self):
        return self.__str__()
    def feeds(self, parts):
        for p in parts:
            p.isfedl.append(self)
            self.feedsl.append(p)
    def isfed(self, parts):
        for p in parts:
            self.isfedl.append(p)
            p.feedsl.append(self)
    def late(self):
        deltas = []
        for feedp in self.feedsl:
            delta = feedp.start - self.finish
            deltas.append(delta)
        #lates should have self.finish > self.start, so negative delta
        lates = [t for t in deltas if t.days < 0]
        if len(lates) > 0:
            self.status = 'LATE'
            self.LATE = True
        elif len(lates) == 0:
            self.status = 'ONTIME'
            self.LATE = False
        return self.status

每个部分都会根据您所拥有的日期根据它输入的内容来跟踪它是准时还是迟到。您可以指定一个部件馈送到另一个部件(更新feedsl部件的isfedl属性和接收者的属性)或指定一个部件由一定数量的部件馈送(同样更新两个属性)。我有一个输入集来假设一个列表,所以如果你一个一个地指定很多,你可以修改或者只是把所有的东西都放在括号里。

完成此操作后,您必须从数据中生成零件列表:

parts = []
LEN = len(data['Tree'])
for i in range(LEN):
    treelev = data['Tree'][i]
    level = data['Level'][i]
    partnum = data['Part #'][i]
    start = data['Sched Start'][i]
    finish = data['Sched Fin'][i]
    parts.append(Part(partnum, level, start, finish))

因此,使用部件列表,您可以使用名称通过列表理解来分隔树Part.part(因为格式的第一个值始终是树编号)。

现在您需要一个接受零件列表的类(假设它们已正确分类到相应的树中),该类通过零件名称生成馈送路径。(这是我想要分号的地方)。

class MaterialTree():
    def __init__(self, parts):
        self.parts = parts
    def setLevTree(self):
        self.levels = [p.level for p in self.parts]
        for ip in range(len(self.parts)-1):
            p = self.parts[ip]
            #all twos feed one:
            if p.level == 1:
                p2s = [p for p in self.parts if p.level == 2]
                p.isfed(p2s)
                continue
            #for each n >= 2, if adjacent is > n, adjacent feeds current
            for l in range(2, max(self.levels)+1):
                pnext = self.parts[ip+1]
                if p.level == pnext.level:
                    continue
                elif p.level == pnext.level-1:
                    p.isfed([pnext])
    def setTree(self):
        #number of production levels
        self.levels = range(max([p.level for p in self.parts]))
        #part names for each level
        self.levdct = {l+1:[p.part for p in self.parts if int(p.part.split(';')[-1][0]) == l+1] for l in self.levels}
        for ik in self.levels[:-1]: #exclude last level, only feeds second to last
            #get names for current base level
            namebase = self.levdct[ik+1]
            #get names for branches one level up
            namebranch = self.levdct[ik+2]
            #select parts with names in base
            base = [p for p in self.parts if p.part in namebase]
            #select parts with names in branch
            branch = [p for p in self.parts if p.part in namebranch]     
            #begin feed:
            for b in base:
                #if there is no letter in the name, all branches feed this
                if not b.part.upper().isupper():
                    for br in branch:
                        br.feeds([b])
                #if there is a letter in the name,
                if b.part.upper().isupper():
                    #select the letter and use it to compare branches
                    letts = [i for i in b.part if i.upper().isupper()][0]
                    #only branches with this letter feed this base
                    for fbr in [br for br in branch if letts in br.part]:
                        fbr.feeds([b])
    def status(self):
        lates = []
        for p in self.parts:
            lates.append(p.late())
        self.status = lates
        return self.status

各种str.upper().isupper()只是测试不同部分名称中是否存在任何字母。如果需要,您可以使用它为您的部件生成状态列表以添加到数据框并导出到 Excel。

只是一个例子:

T1 = [p for p in parts if p.part[0] == '1']
m1 = MaterialTree(T1)
m1.setTree()
print(m1.status())

为我回报['ONTIME', 'ONTIME', 'LATE', 'LATE']

当然,如果您的零件名称具有不易解析但应该可行的结构,它可能会变得更加复杂。

** 编辑 **:如果馈送结构完全由顺序和级别确定(即,具有递增级别的相邻部件馈送当前部件),那么您可以setLevTree改用。它采用这种顺序,但不依赖于零件名称。按照树 2 的相同示例,m.setLevTree()给我['ONTIME', 'ONTIME', 'LATE', 'ONTIME'].

于 2020-04-08T18:19:53.863 回答