我正在尝试找到掩盖段的索引。例如:
mask = [1, 0, 0, 1, 1, 1, 0, 0] segments = [(0, 0), (3, 5)]
当前的解决方案看起来像这样(并且 非常 慢,因为我的掩码包含数百万个数字):
segments = [] start = 0 for i in range(len(mask) - 1): e1 = mask[i] e2 = mask[i + 1] if e1 == 0 and e2 == 1: start = i + 1 elif e1 == 1 and e2 == 0: segments.append((start, i))
有什么办法可以用numpy有效地做到这一点?
我设法对google进行的唯一操作是numpy.ma.notmasked_edges,但它看起来不像我所需要的。
这是一种方法-
def start_stop(a, trigger_val): # "Enclose" mask with sentients to catch shifts later on mask = np.r_[False,np.equal(a, trigger_val),False] # Get the shifting indices idx = np.flatnonzero(mask[1:] != mask[:-1]) # Get the start and end indices with slicing along the shifting ones return zip(idx[::2], idx[1::2]-1)
样品运行-
In [216]: mask = [1, 0, 0, 1, 1, 1, 0, 0] In [217]: start_stop(mask, trigger_val=1) Out[217]: [(0, 0), (3, 5)]
用它来获得0s-
0s
In [218]: start_stop(mask, trigger_val=0) Out[218]: [(1, 2), (6, 7)]
在计时100000x扩大命令datasize -
100000x
In [226]: mask = [1, 0, 0, 1, 1, 1, 0, 0] In [227]: mask = np.repeat(mask,100000) # Original soln In [230]: %%timeit ...: segments = [] ...: start = 0 ...: for i in range(len(mask) - 1): ...: e1 = mask[i] ...: e2 = mask[i + 1] ...: if e1 == 0 and e2 == 1: ...: start = i + 1 ...: elif e1 == 1 and e2 == 0: ...: segments.append((start, i)) 1 loop, best of 3: 401 ms per loop # @Yakym Pirozhenko's soln In [231]: %%timeit ...: slices = np.ma.clump_masked(np.ma.masked_where(mask, mask)) ...: result = [(s.start, s.stop - 1) for s in slices] 100 loops, best of 3: 4.8 ms per loop In [232]: %timeit start_stop(mask, trigger_val=1) 1000 loops, best of 3: 1.41 ms per loop