Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert boolean index to start/end pairs for runs

Tags:

python

numpy

Is there a numpy function that will convert something like:

[0, 1, 0, 1, 1, 1, 0, 1, 1]

to an array of start/end pairs for the contiguous ranges, as:

[[1, 2],
 [3, 6],
 [7, 9]]
like image 893
U2EF1 Avatar asked Sep 16 '13 20:09

U2EF1


2 Answers

Unfortunately I don't have numpy installed but this logic should do it for you.

import itertools
x = [0, 1, 0, 1, 1, 1, 0, 1, 1]

# get the indices where 1->0 and 0->1
diff = np.diff(x) 
diff_index = diff.nonzero(x)

# pair up the ranges using itertools
def pairwise(iterable):
    a, b = itertools.tee(iterable)
    next(b, None)
    return itertools.izip(a, b)

ranges = pairwise(x)

Documentation:

numpy diff
numpy nonzero itertools grouper

like image 67
Serdalis Avatar answered Sep 30 '22 09:09

Serdalis


With the same principle as in @Serdalis answer, but relying solely on numpy:

def start_end(arr):
    idx = np.nonzero(np.diff(arr))[0] + 1
    if arr[0]:
        idx = np.concatenate((np.array([0], dtype=np.intp), idx))
    if arr[-1]:
        idx = np.concatenate((idx, np.array([len(arr)],
                                            dtype=np.intp),))
    return idx.reshape(-1, 2)

>>> start_end([1,1,1,0,0,1,0])
array([[0, 3],
       [5, 6]], dtype=int64)
>>> start_end([0,1,1,1,0,0,1])
array([[1, 4],
       [6, 7]], dtype=int64)
>>> start_end([0,1,1,1,0,0,1,0])
array([[1, 4],
       [6, 7]], dtype=int64)
>>> start_end([1,1,1,0,0,1])
array([[0, 3],
       [5, 6]], dtype=int64)
like image 38
Jaime Avatar answered Sep 30 '22 09:09

Jaime