Looping through multiple arrays with np.where

Viewed 552

I have 2 lists distance_boundary and distance

distance_boundary = [100,200,300]
distance = [125,255,285,140,160,180]

Now I want to create a new variable floor and I want to assign the value for floor based on the distance value and it is defined by distance_boundary

For example ,

distance[0] is 125

since this is between distance_boundary[0] and distance_boundary[1] so the corresponding value for floor should be 1

distance[1] is 255

since this is between distance_boundary[1] and distance_boundary[2] so the corresponding value for floor should be 2

Looping through this should give me the final value of floor as

floor = [1,2,2,1,1,1]

I tried to loop through distance and used to np.where for assignment

floor = []

for j in range(0,len(distance)):

    floor = (np.where((distance[j]>distance_boundary[0]) & (distance[j]>distance_boundary[1]))
                      ,1,2)
    floor.append(floor)

This is not giving me desired result and moreover it is not looking scalable. Is there any other better solution

6 Answers

np.searchsorted seems to be what you are looking for:

np.searchsorted(distance_boundary, distance)
# array([1, 2, 2, 1, 1, 1])

Use pandas.cut:

import pandas as pd

distance_boundary = [100,200,300]
distance = [125,255,285,140,160,180]

[distance_boundary.index(i.right) for i in pd.cut(distance, distance_boundary)]

Output:

[1, 2, 2, 1, 1, 1]

You can try this:

import numpy as np

distance_boundary = np.array([100,200,300])
distance = np.array([125,255,285,140,160,180])

floor = np.zeros_like(distance)
flag = (distance > 100) & (distance < 200)
floor[flag] = 1

flag = (distance > 200) & (distance < 300)
floor[flag] = 2

print(floor)
>>>[1 2 2 1 1 1]

You could use an iterative approach. Sum the result of binary thresholds using each value in distance_boundary as the threshold:

import numpy as np

distance_boundary = np.array([100,200,300])
distance = np.array([125,255,285,140,160,180])

print(sum(np.where(distance > i, 1, 0) for i in distance_boundary))

This will print:

[1 2 2 1 1 1]

O(N log N) solution:

    from bisect import bisect_left

    def binarySearch(num, arr):
        i = bisect_left(arr, num)
        if arr[i] == num:
            return i+1
        else:
            return i


    distance_boundary = [100,200,300]
    distance = [125,255,285,140,160,180]

    floor = list()
    for num in distance:
        floor.append(binarySearch(num, distance_boundary))

    print("floor =", floor)

If your boundaries are always multiples of 100 this will work:

Code:

[int(str(q)[0:-2]) for q in distance]

Out:

[1, 2, 2, 1, 1, 1]
Related