Коротко
np.searchsorted(a, v)— бинарный поиск: индекс, куда вставитьv, чтобыaостался отсортированным. Работает за O(log n).- Массив
aдолжен быть отсортирован по возрастанию — это никто не проверяет. side="left"(по умолчанию) ставит перед равными,side="right"— после. Разница между ними — число вхожденийv.vможет быть массивом: ответ для каждого элемента сразу. Так значения раскладывают по интервалам.np.partition(a, k)ставит на местоk-й по величине элемент: слева меньшие, справа большие, но без сортировки внутри частей. Это быстрее полной сортировки, если нужны только top-k.
Синтаксис
np.searchsorted(a, v, side="left")
np.partition(a, k) # k-й элемент на своём месте
np.partition(a, -k)[-k:] # k наибольших (в произвольном порядке)
np.argpartition(a, k) # то же, но индексыПараметры
ПараметрЧто делаетПо умолчанию
aотсортированный по возрастанию одномерный массивобязательныйvзначение или массив значений для поискаобязательныйside"left" — перед равными, "right" — после"left"kиндекс элемента, который встанет на своё место; отрицательный — с концаобязательныйПримеры
limits = np.array([0, 1000, 5000, 20000]) # границы тарифов, по возрастанию
scores = np.array([72, 45, 90, 58, 81, 39, 66]) # баллы участниковnp.searchsorted(limits, 3000) # куда вставить, чтобы порядок сохранилсяВывод
np.int64(2)
print(np.searchsorted(limits, 5000)) # слева от равного
np.searchsorted(limits, 5000, side="right") # справа от равногоВывод
2 np.int64(3)
spend = np.array([500, 1000, 7500, 25000])
np.searchsorted(limits, spend, side="right") - 1 # номер тарифа для каждой суммыВывод
array([0, 1, 2, 3])
sorted_prices = np.array([90, 120, 250, 480])
pos = np.searchsorted(sorted_prices, 200)
np.insert(sorted_prices, pos, 200)Вывод
array([ 90, 120, 200, 250, 480])
part = np.partition(scores, 2)
print(part[2]) # на месте 2 — третий по величине
print(np.sort(part[:2]), np.sort(part[3:])) # слева меньшие, справа большие; порядок внутри частей любой
np.sort(np.partition(scores, -3)[-3:]) # 3 наибольших (отсортированы уже для вывода)Вывод
58 [39 45] [66 72 81 90] array([72, 81, 90])
idx = np.argpartition(scores, -3)[-3:] # индексы трёх лучших…
idx[np.argsort(scores[idx])[::-1]] # …упорядоченные по убыванию балловВывод
array([2, 4, 0])
Подводные камни
Неотсортированный массив
searchsorted не проверяет порядок и возвращает какое-то число без ошибки. Если данные не отсортированы, сначала np.sort или используйте argsort + sorter=.
np.searchsorted(np.array([5, 1, 3]), 2) # массив не отсортирован — ответ бессмысленныйВывод
np.int64(2)
partition не сортирует части
После partition упорядочен только один элемент — k-й. Если top-k нужны по порядку, отсортируйте эти k элементов отдельно, как в примере выше.