Kenenbek Arzymatov
Kenenbek Arzymatov

Reputation: 9139

How to find a distance between elements in numpy array?

For example, I have such array z: array([1, 0, 1, 0, 0, 0, 1, 0, 0, 1])

How to find a distances between two successive 1s in this array? (measured in the numbers of 0s)

For example, in the z array, such distances are:

[1, 3, 2]

I have such code for it:

distances = []
prev_idx = 0
for idx, element in enumerate(z):
    
    if element == 1:
        distances.append(idx - prev_idx)
        prev_idx = idx

distances = np.array(distances[1:]) - 1

Can this opeartion be done without for-loop and maybe in more efficient way?

UPD

The solution in the @warped answer works fine in 1-D case. But what if z will be 2D-array like np.array([z, z])?

Upvotes: 4

Views: 2224

Answers (2)

warped
warped

Reputation: 9481

You can use np.where to find the ones, and then np.diff to get the distances:

q=np.where(z==1)
np.diff(q[0])-1

out:

array([1, 3, 2], dtype=int64)

edit:

for 2d arrays:

You can use the minimum of the manhattan distance (decremented by 1) of the positions that have ones to get the number of zeros inbetween:

def manhattan_distance(a, b):
    return np.abs(np.array(a) - np.array(b)).sum()

zeros_between = []

r, c = np.where(z==1)
coords = list(zip(r,c))

for i, c in enumerate(coords[:-1]):
    
    zeros_between.append(
    np.min([manhattan_distance(c, coords[j])-1 for j in range(i+1, len(coords))]))

Upvotes: 7

engmmcasas
engmmcasas

Reputation: 31

If you dont want to use the for, you can use np.where and np.roll

import numpy as np
x = np.array([1, 0, 1, 0, 0, 0, 1, 0, 0, 1])
pos = np.where(x==1)[0] #pos = array([0, 2, 6, 9])
shift = np.roll(pos,-1) # shift = array([2, 6, 9, 0])
result = ((shift-pos)-1)[:-1] 
#shift-pos = array([ 2,  4,  3, -9])
#(shif-pos)-1 = array([ 1,  3,  2, -10])
#((shif-pos)-1)[:-1] = array([ 1,  3,  2])
print(result)

Upvotes: 3

Related Questions