两个时间段的重叠

时间:2019-01-14 17:55:22

标签: python datetime

我有两个数据框。

其中包含工人的上班时间以及开始日期和结束日期。

另一个是“停机时间”,它具有开始时间和结束时间。

两个数据帧都如下所示:

    Start Date                  End Date               

43  2018-10-01 05:00:00+00:00   2018-10-03 05:00:00+00:00   
44  2018-09-27 13:00:00+00:00   2018-10-01 05:00:00+00:00 
45  2018-09-27 10:10:00+00:00   2018-09-27 13:00:00+00:00 

我正在寻找员工实际工作的时间。仅计算不是停机时间的时间。

我想到了两种解决方法(得出的结果略有不同)

第一个是“暴力法”,其中我创建一个新的数据框,其中包含一年中每分钟的记录。我将此与轮班时间结合起来,以便将所有工人时间分成1分钟间隔。然后,我使用了以下代码

removed_stuff = pd.DataFrame(columns=["shift","columns"])

for i in range(len(downtime)):

    removed_stuff = pd.concat([removed_stuff,test_copy[(test_copy.index <= downtime["End Date"][i]) & (test_copy.index >= downtime["Start Date"][i])]])

    test_copy = test_copy[(test_copy.index > downtime["End Date"][i]) | (test_copy.index < downtime["Start Date"][i])]

removed_stuff是planned_stoppage_reasons开始和结束时间内所有已除去的东西。 test_copy是我想要的,并且包含所有停机时间之外的所有时间。

在累加test_copy I的分钟数(应该)时,得出的总分钟数超出了已进行的任何停机时间。

我的另一个主意是波浪形的手。

我将停机时间和工作人员转移合并到一个数据帧中:

time                   shift start  shift end stoppage start    stoppage end    
2018-01-02 06:00:00+00:00   NaN     NaN     1.0     NaN 
2018-01-02 18:30:00+00:00   NaN     NaN     NaN     1.0 
2018-01-04 06:00:00+00:00   1.0     NaN     NaN     NaN 
2018-01-04 18:00:00+00:00   NaN     1.0     NaN     NaN 
2018-01-05 06:00:00+00:00   1.0     NaN     NaN     NaN 
2018-01-05 18:00:00+00:00   NaN     1.0     NaN     NaN 

然后我创建一个新列,该列按以下方式编写。

def actaul_shift(Dataframe,first_value):

    Dataframe_new = Dataframe.copy()

    Dataframe_new["actual"][0] = first_value

    for i in range(len(Dataframe_new)):
        if i != 0:
            if Dataframe_new["shift start"][i] == 1:
                Dataframe_new["actual"][i] = Dataframe_new["actual"][i - 1] + 1
            elif Dataframe_new["shift end"][i] == 1:
                Dataframe_new["actual"][i] = Dataframe_new["actual"][i -1] - 1
            elif Dataframe_new["stoppage start"][i] == 1:
                Dataframe_new["actual"][i] = Dataframe_new["actual"][i -1] - 1
            elif Dataframe_new["stoppage end"][i] == 1:
                Dataframe_new["actual"][i] = Dataframe_new["actual"][i -1] + 1

    return Dataframe_new

我必须指定第一个值(这是机器应该在第一时间打开还是关闭),之后,如果shift start == 1,则实际列应将1添加到先前值,如果shift end == 1,则将前一个值减1;如果stoptop start == 1,则将前一个值减1;如果stop end end == 1,则将1之前的值加1。

然后,基本上我只关心数字从1到0(从开到关)的转变。

如果机器在关闭状态下启动(0),然后停机时间开始(-1),那么换档开始时间(0),然后停机时间结束(1),然后换档时间结束(0)。剩下的时间里,当机器停机时,只有最后的1到0计数。

在一张纸上运行一些示例似乎总是有意义的。

但是,我从两种方法获得的结果却略有不同。结果足够大(相差9%),我无法通过第一种方法的简单舍入误差来解释它(我什至每隔1秒运行一次,结果仍然不一样)。

这两种方法都正确吗?如果是这样,那么有一个更有效的方法,如果没有,那就是一种正确的方法。

非常感谢

1 个答案:

答案 0 :(得分:0)

从注释中请求的示例开始工作,并且要确定停机时间实际上可能不在工作班次之内(这是错的,但是,这是您的数据),您可以使用这些时间找到四个小时的总工作时间步骤:

>>> from datetime import datetime
>>> fmt = '%Y-%m-%d %H:%M:%S'
>>> S1 = datetime.strptime('2018-01-02 06:00:00', fmt)
>>> E1 = datetime.strptime('2018-01-02 18:30:00', fmt)
>>> S2 = datetime.strptime('2018-01-02 10:00:00', fmt)
>>> E2 = datetime.strptime('2018-01-02 20:00:00', fmt)

>>> shift = max(E1, E2) - min(S1, S2)
>>> downtime = E2 - S2
>>> worked = shift - downtime
>>> worked.seconds
14400
>>> worked.seconds / 60 / 60
4.0