使用NumPy查找条件为True的span

6mw9ycah  于 9个月前  发布在  其他
关注(0)|答案(3)|浏览(108)

假设我有一个numpy数组,我需要找到条件为True的spans/ranges。例如,我有以下数组,我试图在其中查找项大于1的spans:

[0, 0, 0, 2, 2, 0, 2, 2, 2, 0]

字符串
我需要找到索引(开始,停止):

(3, 5) 
(6, 9)


我能够实现的最快的事情是制作一个布尔数组:

truth = data > threshold


然后使用numpy.argminnumpy.argmax遍历数组以找到开始和结束位置。

pos = 0
    truth = container[RATIO,:] > threshold

    while pos < len(truth):
        start = numpy.argmax(truth[pos:]) + pos + offset
        end = numpy.argmin(truth[start:]) + start  + offset
        if not truth[start]:#nothing more
            break
        if start == end:#goes to the end
            end = len(truth)
        pos = end


但是这对于我的数组中的数十亿个位置来说太慢了,而且我找到的跨度通常只是一行中的几个位置。有人知道更快的方法来找到这些跨度吗?

pwuypxnk

pwuypxnk1#

一种方法如何。首先取你拥有的布尔数组:

In [11]: a
Out[11]: array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0])

In [12]: a1 = a > 1

字符串
使用roll将其向左移动一个(以获得每个索引处的下一个状态):

In [13]: a1_rshifted = np.roll(a1, 1)

In [14]: starts = a1 & ~a1_rshifted  # it's True but the previous isn't

In [15]: ends = ~a1 & a1_rshifted


其中non-zero是每个True批次的开始(或结束批次):

In [16]: np.nonzero(starts)[0], np.nonzero(ends)[0]
Out[16]: (array([3, 6]), array([5, 9]))


把这些放在一起:

In [17]: zip(np.nonzero(starts)[0], np.nonzero(ends)[0])
Out[17]: [(3, 5), (6, 9)]

ymdaylpp

ymdaylpp2#

如果您有访问scipy库的权限:
你可以使用scipy.ndimage.measurements.label来识别任何非零值的区域。它返回一个数组,其中每个元素的值是原始数组中跨度或范围的ID。
然后,您可以使用scipy.ndimage.measurements.find_objects返回提取这些范围所需的切片。您可以直接从这些切片访问开始/结束值。
在您的示例中:

import numpy
from scipy.ndimage.measurements import label, find_objects

data = numpy.array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0])

labels, number_of_regions = label(data)
ranges = find_objects(labels)

for identified_range in ranges:
    print(identified_range[0].start, identified_range[0].stop)

字符串
您应该看到:

3 5
6 9


希望这对你有帮助!

0sgqnhkj

0sgqnhkj3#

而不是使用np.roll,它有一个严重的问题,它滚动。你最好只做两个副本。一个与右垫和左垫。我需要这个图像。

a = np.pad(im, ((0, 0), (0, 1)), constant_values=0)
        b = np.pad(im, ((0, 0), (1, 0)), constant_values=0)
        starts = a & ~b
        ends = ~a & b
        sx, sy = np.nonzero(starts)
        ex, ey = np.nonzero(ends)

字符串
认可的答案有一个问题,如果你以True结尾,它会滚到前面,把值弄乱。你真的想用0填充这些值。
然后你找到1 -> 0的转换和0 -> 1的转换,并把它们放在你需要的格式。

相关问题