[python] NumPy 배열에서 N 최대 값의 인덱스를 어떻게 얻습니까?

NumPy는 다음을 통해 배열의 최대 값 인덱스를 얻는 방법을 제안합니다. np.argmax .

비슷한 것을 원하지만 N최대 값 의 색인을 반환 합니다.

I 배열이있는 경우 예를 들어 [1, 3, 2, 4, 5], function(array, n=3)인덱스 반환 [4, 3, 1]요소에 대응 [5, 4, 3].



답변

내가 생각해 낸 가장 간단한 방법은 다음과 같습니다.

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

여기에는 완전한 배열이 포함됩니다. numpy부분 정렬을 수행하는 기본 제공 방법을 제공 하는지 궁금합니다 . 지금까지 나는 하나를 찾을 수 없었습니다.

이 솔루션이 너무 느리면 (특히 작은 경우 n) Cython 에서 코드를 작성하는 것이 좋습니다.


답변

최신 NumPy 버전 (1.8 이상)에는이를 argpartition위한 함수가 있습니다 . 네 가지 가장 큰 요소의 지수를 얻으려면

>>> a = np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
>>> a
array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
>>> ind = np.argpartition(a, -4)[-4:]
>>> ind
array([1, 5, 8, 0])
>>> a[ind]
array([4, 9, 6, 9])

와 달리이 argsort함수는 최악의 경우 선형 시간으로 실행되지만 평가 결과에서 볼 수 있듯이 반환 된 인덱스는 정렬되지 않습니다 a[ind]. 필요한 경우 나중에 정렬하십시오.

>>> ind[np.argsort(a[ind])]
array([1, 8, 5, 0])

이런 식으로 최상위 k 요소를 정렬 된 순서로 얻으려면 O ( n + k log k ) 시간이 걸립니다.


답변

더 간단하면서도 :

idx = (-arr).argsort()[:n]

여기서 n 은 최대 값 수입니다.


답변

사용하다:

>>> import heapq
>>> import numpy
>>> a = numpy.array([1, 3, 2, 4, 5])
>>> heapq.nlargest(3, range(len(a)), a.take)
[4, 3, 1]

일반 파이썬 목록의 경우 :

>>> a = [1, 3, 2, 4, 5]
>>> heapq.nlargest(3, range(len(a)), a.__getitem__)
[4, 3, 1]

Python 2를 사용 xrange하는 경우 대신range .

출처 : heapq — 힙 큐 알고리즘


답변

다차원 배열로 작업하는 경우 인덱스를 평평하게하고 풀어야합니다.

def largest_indices(ary, n):
    """Returns the n largest indices from a numpy array."""
    flat = ary.flatten()
    indices = np.argpartition(flat, -n)[-n:]
    indices = indices[np.argsort(-flat[indices])]
    return np.unravel_index(indices, ary.shape)

예를 들면 다음과 같습니다.

>>> xs = np.sin(np.arange(9)).reshape((3, 3))
>>> xs
array([[ 0.        ,  0.84147098,  0.90929743],
       [ 0.14112001, -0.7568025 , -0.95892427],
       [-0.2794155 ,  0.6569866 ,  0.98935825]])
>>> largest_indices(xs, 3)
(array([2, 0, 0]), array([2, 2, 1]))
>>> xs[largest_indices(xs, 3)]
array([ 0.98935825,  0.90929743,  0.84147098])


답변

사용할 수 있는 K 번째로 큰 요소 의 순서 에 신경 쓰지 않으면 argpartition전체 정렬보다 성능이 우수합니다 argsort.

K = 4 # We want the indices of the four largest values
a = np.array([0, 8, 0, 4, 5, 8, 8, 0, 4, 2])
np.argpartition(a,-K)[-K:]
array([4, 1, 5, 6])

크레딧은 이 질문으로 갑니다 .

몇 가지 테스트를 실행 했으며 배열의 크기와 K의 값이 증가함에 따라 argpartition성능이 뛰어 argsort납니다.


답변

다차원 배열의 경우 axis키워드를 사용 하여 예상 축을 따라 분할을 적용 할 수 있습니다 .

# For a 2D array
indices = np.argpartition(arr, -N, axis=1)[:, -N:]

그리고 아이템을 잡기 위해 :

x = arr.shape[0]
arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)

그러나 이렇게하면 정렬 된 결과가 반환되지 않습니다. 이 경우 np.argsort()원하는 축을 따라 사용할 수 있습니다 .

indices = np.argsort(arr, axis=1)[:, -N:]

# Result
x = arr.shape[0]
arr[np.repeat(np.arange(x), N), indices.ravel()].reshape(x, N)

예를 들면 다음과 같습니다.

In [42]: a = np.random.randint(0, 20, (10, 10))

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

In [45]: np.argpartition(a, np.argmin(a, axis=0))[:, 1:] # 1 is because the first item is the minimum one.
Out[45]:
array([[4, 5, 6, 8, 0, 7, 9, 1, 2],
       [2, 7, 5, 9, 6, 8, 1, 0, 4],
       [5, 8, 1, 9, 7, 3, 6, 2, 4],
       [4, 5, 2, 6, 3, 9, 0, 8, 7],
       [7, 2, 6, 4, 1, 3, 8, 5, 9],
       [2, 3, 5, 7, 6, 4, 0, 9, 1],
       [4, 3, 0, 7, 8, 5, 1, 2, 9],
       [5, 2, 0, 8, 4, 6, 3, 1, 9],
       [0, 1, 9, 4, 3, 7, 5, 2, 6],
       [0, 4, 7, 8, 5, 1, 9, 2, 6]])

In [46]: np.argpartition(a, np.argmin(a, axis=0))[:, -3:]
Out[46]:
array([[9, 1, 2],
       [1, 0, 4],
       [6, 2, 4],
       [0, 8, 7],
       [8, 5, 9],
       [0, 9, 1],
       [1, 2, 9],
       [3, 1, 9],
       [5, 2, 6],
       [9, 2, 6]])

In [89]: a[np.repeat(np.arange(x), 3), ind.ravel()].reshape(x, 3)
Out[89]:
array([[10, 11, 12],
       [16, 16, 18],
       [13, 15, 18],
       [14, 18, 19],
       [16, 18, 19],
       [14, 14, 19],
       [15, 18, 19],
       [16, 17, 19],
       [ 9, 14, 14],
       [12, 15, 18]])