确定考虑重叠的总时间的有效方法

时间:2017-08-14 19:24:52

标签: python pandas time overlap calculation

我正在使用pandas数据帧:

我试图找到确定船舶在特定泊位上花费的总时间的最佳方法,同时考虑到访问持续时间的重叠。 以下是数据的样子:

 IN                    OUT                        BERTH 
2015-01-14 13:57:00   2015-01-15 17:15:00         01
2015-01-14 14:30:00   2015-01-15 02:50:00         01
2015-01-14 14:30:00   2015-01-16 06:10:00         01
2015-01-25 02:15:00   2015-01-26 13:41:00         01

我想要的是找出使用特定泊位的总时间。所以看数据有重叠,所以我不能简单地为每条记录添加时间。

看看上面的数据,我们可以看到第二次发货的时间完全在第一次,因此记录的时间为0,第三艘船在第一次发货之前,但一直停留到第一次发货后,所以这里时间将是=(从第1次发货开始 - 然后我们将移动到下一个,因为那里没有重叠,只需将[4中的4个]添加到停泊的总时间1 ,并继续这直到最后产生这样的事情:

BERTH   HOURS WORKED
  01    7.750
  02    10.275
  03    5.585
  08    31.980

1 个答案:

答案 0 :(得分:1)

这是一个泊位的解决方案。我希望你能把它扩展到多个泊位。

将数据框拆分为到达和离开:

dfIN = df[['IN']]
dfOUT = df[['OUT']]
dfIN['direction'] = 1
dfOUT['diretcion'] = -1

截至目前,IN和OUT只是时间戳:

dfIN.columns = ('TS', 'direction')
dfOUT.columns = ('TS', 'direction')

将这两个部分合并为一个高排序的流量数据框:

traffic = pd.concat([dfIN, dfOUT]).sort_values('TS')
#                   TS  direction
#0 2015-01-14 13:57:00          1
#1 2015-01-14 14:30:00          1
#2 2015-01-14 14:30:00          1
#1 2015-01-15 02:50:00         -1
#0 2015-01-15 17:15:00         -1
#2 2015-01-16 06:10:00         -1
#3 2015-01-25 02:15:00          1
#3 2015-01-26 13:41:00         -1

计算泊位到达和离开时的船舶数量:

traffic['ships'] = traffic['direction'].cumsum()

确定泊位为空的时间段。然后计算每个“繁忙时段”的序列号。

traffic['empty'] = (traffic['ships'] == 0).shift().fillna(0).astype(int)
traffic['busy_id'] = traffic['empty'].cumsum()
#                   TS  direction  ships  empty busy_id
#0 2015-01-14 13:57:00          1      1      0       0
#1 2015-01-14 14:30:00          1      2      0       0
#2 2015-01-14 14:30:00          1      3      0       0
#1 2015-01-15 02:50:00         -1      2      0       0
#0 2015-01-15 17:15:00         -1      1      0       0
#2 2015-01-16 06:10:00         -1      0      0       0
#3 2015-01-25 02:15:00          1      1      1       1
#3 2015-01-26 13:41:00         -1      0      0       1

计算每个“忙碌期”的开始和结束:

busy_data = traffic.groupby('busy_id')['TS'].agg([min, max])
#                      min                 max
#busy_id                                        
#0     2015-01-14 13:57:00 2015-01-16 06:10:00
#1     2015-01-25 02:15:00 2015-01-26 13:41:00

计算所有“繁忙时段”的总长度:

(busy_data['max'] - busy_data['min']).sum()
#Timedelta('3 days 03:39:00')