使用NumPy查找条件为True的范围

ACE*_*ish 4 python arrays search numpy

想象一下,我有一个numpy数组,我需要找到条件为True的跨度/范围.例如,我有以下数组,其中我试图找到项大于1的跨度:

[0, 0, 0, 2, 2, 0, 2, 2, 2, 0]
Run Code Online (Sandbox Code Playgroud)

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

(3, 5) 
(6, 9)
Run Code Online (Sandbox Code Playgroud)

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

truth = data > threshold
Run Code Online (Sandbox Code Playgroud)

然后使用numpy.argmin和循环遍历数组并numpy.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
Run Code Online (Sandbox Code Playgroud)

但是对于数组中的数十亿个位置来说这已经太慢了,而且我发现的跨度通常只是连续几个位置.有谁知道找到这些跨度的更快的方法?

And*_*den 5

怎么一个方法.首先获取您拥有的布尔数组:

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

In [12]: a1 = a > 1
Run Code Online (Sandbox Code Playgroud)

使用以下方法将其向左移一(以获得每个索引处的下一个状态)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
Run Code Online (Sandbox Code Playgroud)

如果不为零则是每个True批次(或分别为结束批次)的开始:

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

并将这些拼凑在一起:

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