Reputation: 7524
I've an array of values and want to map each value with one from another array. The mapped value is the largest found which is lower or equal (I make the assumption it always exists).
For example from the values [6, 15, 4, 12, 10, 5]
and the lookup table [4, 6, 7, 8, 10, 12]
I would print:
6 is between 6 and 7
15 is between 12 and None
4 is between 4 and 6
12 is between 12 and None
10 is between 10 and 12
5 is between 4 and 6
I do this like this:
import numpy as np
def last_smallest(values, limits):
count = values.shape[0]
value = np.zeros(count, dtype='int')
for i in range(count):
found = np.where(limits <= values[i])
value[i] = found[-1][-1]
return value
lookup_table = np.array([4, 6, 7, 8, 10, 12])
samples = np.array([6, 15, 4, 12, 10, 5])
result = last_smallest(samples, lookup_table)
for i, value in enumerate(samples):
index = result[i]
high = lookup_table[index+1] if index < lookup_table.shape[0] - 1 else None
print(f'{value} is between {lookup_table[index]} and {high}')
This works, however last_smallest
function is really not elegant. I've tried to vectorize it, but I can't.
Is it possible to replace result = last_smallest(samples, lookup_table)
by pure numpy
array operations?
Upvotes: 0
Views: 117
Reputation: 3368
np.digitize
can be used here:
lookup_table = np.array([4, 6, 7, 8, 10, 12])
samples = np.array([6, 15, 4, 12, 10, 5])
res = np.digitize(samples, lookup_table)
lookup_table = np.append(lookup_table, None) # you might want to change this line
for sample, idx in zip(samples, res):
print(f'{sample} is between {lookup_table[idx-1]} and {lookup_table[idx]}')
Output:
6 is between 6 and 7
15 is between 12 and None
4 is between 4 and 6
12 is between 12 and None
10 is between 10 and 12
5 is between 4 and 6
Upvotes: 1