我有两个数据框。
其中包含工人的上班时间以及开始日期和结束日期。
另一个是“停机时间”,它具有开始时间和结束时间。
两个数据帧都如下所示:
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秒运行一次,结果仍然不一样)。
这两种方法都正确吗?如果是这样,那么有一个更有效的方法,如果没有,那就是一种正确的方法。
非常感谢
答案 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