How to accessing indices in an array at transition in an array from one to another value (python)

Viewed 60

I have an array like:

val=[[1,1,1,0,0,1,1,0,0,0], [0,1,1,1,0,1,1,0,0,0]]

I would like to access the indices where the value changes from 1 to 0.

Expected output is like:

    [[(2,3),(4,5),(6,7)],[(0,1),(3,4),(4,5),(6,7)]]

I tried with np.gradient function, and able to find the gradient value. Instead of this is any better method:

X=np.gradient(val,axis=1)
Y=np.gradient(val,axis=0)
         
trans_YX = np.array(list(zip(Y.ravel(),X.ravel())),dtype('f4,f4')).reshape(Y.shape)

Current output:

[[(-1.,  0. ) ( 0.,  0. ) ( 0., -0.5) ( 1., -0.5) ( 0.,  0.5) ( 0.,  0.5)
  ( 0., -0.5) ( 0., -0.5) ( 0.,  0. ) ( 0.,  0. )]
 [(-1.,  1. ) ( 0.,  0.5) ( 0.,  0. ) ( 1., -0.5) ( 0.,  0. ) ( 0.,  0.5)
  ( 0., -0.5) ( 0., -0.5) ( 0.,  0. ) ( 0.,  0. )]]
3 Answers

Here is a semi-numpy solution:

val = [[1,1,1,0,0,1,1,0,0,0], [0,1,1,1,0,1,1,0,0,0]]

a = np.array(val)

mask = a[:, :-1] != a[:, 1:]
# array([[False, False,  True, False,  True, False,  True, False, False],
#        [ True, False, False,  True,  True, False,  True, False, False]])

idx = np.arange(mask.shape[1])
# array([0, 1, 2, 3, 4, 5, 6, 7, 8])

out = [list(zip((x:=idx[m]), x+1)) for m in mask]

output: [[(2, 3), (4, 5), (6, 7)], [(0, 1), (3, 4), (4, 5), (6, 7)]]

If pure python works for our solution. you can apply the methodology to each row:

[(i, i + 1) for i in range(len((val_row)) - 1) if val_row[i] != val_row[i+1]]

Please notice you indices are x and x+1 so one must look for x itself.

Here numpy.diff can get the difference between value and neighboring value. Using numpy.where one can find the indices of some specific conditions (such as no equal to 0)

Next you can organize the results:

import numpy as np

val=[[1,1,1,0,0,1,1,0,0,0], [0,1,1,1,0,1,1,0,0,0]]

result = [
    [
        (i, i + 1)
        for i in np.where(np.diff(each) != 0)[0]
    ]
    for each in val
]

print(result)
Related