Мне нужно N минимальных (индексных) значений в массиве numpy

Привет У меня есть массив с X количеством значений в нем. Я хотел бы найти индексы десяти наименьших значений. В этой ссылке они рассчитали максимально эффективно, Как получить индексы N максимальных значений в массиве numpy? однако я не могу прокомментировать ссылки, поэтому мне нужно перепросить вопрос.

Я не уверен, какие индексы мне нужно изменить для достижения минимальных, а не максимальных значений. Это их код

In [1]: import numpy as np

In [2]: arr = np.array([1, 3, 2, 4, 5])

In [3]: arr.argsort()[-3:][::-1]
Out[3]: array([4, 3, 1]) 

Ответ 1

Если вы вызываете

arr.argsort()[:3]

Он даст вам индексы трех наименьших элементов.

array([0, 2, 1], dtype=int64)

Итак, для n вы должны позвонить

arr.argsort()[:n]

Ответ 2

Поскольку этот вопрос был отправлен, numpy обновил, чтобы включить более быстрый способ выбора наименьших элементов из массива с помощью argpartition. Он был впервые включен в Numpy 1.8.

Используя критический ответ в качестве вдохновения, мы можем быстро найти наименьшие элементы k=3:

In [1]: import numpy as np

In [2]: arr = np.array([1, 3, 2, 4, 5])

In [3]: k = 3

In [4]: ind = np.argpartition(arr, k)[:k]

In [5]: ind
Out[5]: array([0, 2, 1])

In [6]: arr[ind]
Out[6]: array([1, 2, 3])

Это будет работать в O (n) раз, потому что ему не нужно делать полный сортировку. Если вам нужны ваши ответы отсортированы ( Примечание:, в этом случае выходной массив был в отсортированном порядке, но это не гарантировано), вы можете отсортировать вывод:

In [7]: sorted(arr[ind])
Out[7]: array([1, 2, 3])

Это выполняется на O (n + k log k), поскольку сортировка выполняется на меньших вывода.

Ответ 3

Я не гарантирую, что это будет быстрее, но лучший алгоритм будет полагаться на heapq.

import heapq
indices = heapq.nsmallest(10,np.nditer(arr),key=arr.__getitem__)

Это должно работать примерно в O(N), тогда как при использовании argsort будут выполняться операции O(NlogN). Тем не менее, другой переносится в сильно оптимизированный C, поэтому он все равно может работать лучше. Чтобы точно знать, вам нужно будет запустить некоторые тесты по вашим фактическим данным.

Ответ 4

Просто не меняйте результаты сортировки.

In [164]: a = numpy.random.random(20)

In [165]: a
Out[165]: 
array([ 0.63261763,  0.01718228,  0.42679479,  0.04449562,  0.19160089,
        0.29653725,  0.93946388,  0.39915215,  0.56751034,  0.33210873,
        0.17521395,  0.49573607,  0.84587652,  0.73638224,  0.36303797,
        0.2150837 ,  0.51665416,  0.47111993,  0.79984964,  0.89231776])

Сортировка:

In [166]: a.argsort()
Out[166]: 
array([ 1,  3, 10,  4, 15,  5,  9, 14,  7,  2, 17, 11, 16,  8,  0, 13, 18,
       12, 19,  6])

Первая десятка:

In [168]: a.argsort()[:10]
Out[168]: array([ 1,  3, 10,  4, 15,  5,  9, 14,  7,  2])