python在数组中查找交集时间范围

时间:2016-02-03 17:13:12

标签: python algorithm numpy

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

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

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

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

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

是否有一个优雅的解决方案,以便在"短"时间(例如,低于一分钟)?

2 个答案:

答案 0 :(得分:2)

将数据存储为(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))加上一些开销。

答案 1 :(得分:1)

鉴于可能没有对输入列表进行排序并处理我们可能会看到具有多个交叉点的时间范围的情况,这里使用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]])

如果within中的 "if any start time or end time is within an other timerange" ,则表示边界具有包容性,请将 > 的比较更改为 >=