【问题标题】:python find intersection timeranges in arraypython在数组中查找交集时间范围
【发布时间】:2016-02-03 17:13:11
【问题描述】:

我有一个两行的 python numpy 数组。一行描述事件的开始时间,另一行描述结束时间(此处时间为纪元整数)。代码示例意味着,index=0 处的事件从 time=1 开始,在 time=7 结束。

start = [1, 8, 15, 30]
end   = [7, 16, 20, 40]

timeranges = np.array([start,end]) 

我想知道时间范围是否相交。这意味着我需要一个函数/算法来计算信息,即从 8 到 16 的时间范围与从 15 到 20 的时间范围相交。

我的解决方案是,使用两个相交的循环并检查任何开始时间或结束时间是否在另一个时间范围内。但是使用 ipython 它会持续很长时间,因为我的 timeranges 充满了近 10000 个事件。

是否有一个优雅的解决方案,可以在“短”时间内(例如,不到一分钟)获得结果?

【问题讨论】:

  • 那么,输出只是一个标志(真/假)?
  • 我想获取发生这种情况的索引,因为它表示失败。
  • 那么,列出的示例数据的确切输出是什么?另外,数据是否已经针对开始和结束进行了排序?
  • 列表未排序。输出应该以我可以在数组中找到响应索引的方式提供每个交叉点的信息。我的循环解决方案适用于这种情况:'end_index=1, intersect_index=2' 和 'start_index=2, intersect_index=1'。只要找到其中一个就足够了。

标签: python algorithm numpy


【解决方案1】:

将数据存储为(time,index_in_list,start_or_end) 的集合。例如,如果输入数据是:

start = [1, 8, 15, 30]
end   = [7, 16, 20, 40]

将输入数据转换为元组列表,如下所示:

def extract_times(times,is_start):
   return [(times[i],i,is_start) for i in range(len(times))]

产量:

extract_times(start,true) == [(1,0,true),(8,1,true),(15,2,true),(30,3,true)]
extract_times(end,false) == [(7,0,false),(16,1,false),(20,2,false),(40,3,false)]

现在,合并两个列表并存储它们。 然后,开始从头到尾遍历列表,每次都跟踪当前相交的区间,根据每个新元组是区间的开始还是结束来更新状态。这样你会发现所有的重叠。

复杂度是O(n log(n)) 排序加上一些开销,如果有很多交叉点。

【讨论】:

    【解决方案2】:

    鉴于输入列表可能未排序,并且为了处理我们可能会看到具有多个交叉点的时间范围的情况,这里有一个基于蛮力比较的方法,使用 broadcasting -

    np.argwhere(np.triu(timeranges[1][:,None] > timeranges[0],1))
    

    样本运行

    原始样例:

    In [81]: timeranges
    Out[81]: 
    array([[ 1,  8, 15, 30],
           [ 7, 16, 20, 40]])
    
    In [82]: np.argwhere(np.triu(timeranges[1][:,None] > timeranges[0],1))
    Out[82]: array([[1, 2]])
    

    多个路口案例:

    In [77]: timeranges
    Out[77]: 
    array([[ 5,  7, 18, 12, 19],
           [11, 17, 28, 19, 28]])
    
    In [78]: np.argwhere(np.triu(timeranges[1][:,None] > timeranges[0],1))
    Out[78]: 
    array([[0, 1],
           [1, 3],
           [2, 3],
           [2, 4]])
    

    如果"if any start time or end time is within an other timerange"中的within表示边界是包容的,请将>的比较改为>= strong> 在解决方案代码中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-07
      • 1970-01-01
      • 2016-04-14
      • 1970-01-01
      • 2019-11-08
      • 1970-01-01
      • 2018-04-09
      • 2019-01-03
      相关资源
      最近更新 更多