#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. Это именно то, что я пытался сделать: Биннинг, но я совсем не знал об этой функции.