【问题标题】:Efficient way to determine total time taking overlap into account考虑重叠来确定总时间的有效方法
【发布时间】:2017-08-14 19:24:52
【问题描述】:

我将 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,而第三艘船在第一艘船之前到达,但一直停留到第一艘船离开之后,所以在这里时间为 = (out of 3rd ship - in of 1) 然后我们将移至下一艘,因为那里没有重叠,只需将 [out of 4 - in of 4] 添加到泊位 1 的总时间,并一直持续到最后产生类似这样的东西:

BERTH   HOURS WORKED
  01    7.750
  02    10.275
  03    5.585
  08    31.980

【问题讨论】:

  • 你能告诉我们你到目前为止尝试了什么吗?我会首先建立一个时间间隔列表,当你处理一个新的间隔时,检查它是否部分(或全部)落在你现有的间隔内,如果是,根据需要修改现有的间隔。
  • 到目前为止,我只尝试了一些带有一堆 if 语句的 for 循环,但它似乎从未捕捉到所有情况。但我明白你在说什么,我将尝试 DYZ 刚刚给出的解决方案。谢谢!

标签: python pandas time overlap calculation


【解决方案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')

【讨论】:

  • 谢谢!我很快就会尝试这个解决方案。试过后会更新。
猜你喜欢
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多