Векторизация поиска

#python #numpy #vectorization

Вопрос:

У меня есть массив значений, и я хочу сопоставить каждое значение с одним из другого массива. Отображенное значение-это наибольшее найденное значение, которое меньше или равно (я предполагаю, что оно всегда существует).

Например, из значений [6, 15, 4, 12, 10, 5] и таблицы поиска [4, 6, 7, 8, 10, 12] , которые я бы напечатал:

 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
 

Я делаю это вот так:

 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}')
 

Это работает, однако last_smallest функция на самом деле не элегантна. Я пытался его векторизировать, но не могу.

Можно ли заменить result = last_smallest(samples, lookup_table) операции с чистым numpy массивом?

Комментарии:

1. np.searchsorted(lookup_table, samples) даст индекс для каждого значения в samples

Ответ №1:

np.digitize можно использовать здесь:

 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]}')
 

Выход:

 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
 

Комментарии:

1. Это именно то, что я пытался сделать: Биннинг, но я совсем не знал об этой функции.