Programing

파이썬에서 정렬 된 배열의 인덱스를 얻는 방법

lottogame 2020. 5. 24. 10:44
반응형

파이썬에서 정렬 된 배열의 인덱스를 얻는 방법


숫자 목록이 있습니다.

myList = [1, 2, 3, 100, 5]

이제이 목록을 정렬하면 얻을 수 [1, 2, 3, 5, 100]있습니다. 내가 원하는 것은 정렬 된 순서대로 원래 목록의 요소 인덱스입니다. 즉 [0, 1, 2, 4, 3], 값과 인덱스를 모두 반환하는 ala MATLAB의 정렬 함수입니다.


numpy를 사용하는 경우 argsort () 함수를 사용할 수 있습니다.

>>> import numpy
>>> numpy.argsort(myList)
array([0, 1, 2, 4, 3])

http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html

배열 또는 목록을 정렬하는 인수를 반환합니다.


다음과 같은 것 :

>>> myList = [1, 2, 3, 100, 5]
>>> [i[0] for i in sorted(enumerate(myList), key=lambda x:x[1])]
[0, 1, 2, 4, 3]

enumerate(myList) (색인, 값)의 튜플을 포함하는 목록을 제공합니다.

[(0, 1), (1, 2), (2, 3), (3, 100), (4, 5)]

목록을 전달 sorted하고 정렬 키 (각 튜플의 두 번째 요소; 추출 대상)를 추출하는 함수를 지정 하여 목록을 정렬합니다 lambda. 마지막으로, 정렬 된요소 의 원래 색인은 [i[0] for i in ...]목록 이해를 사용하여 추출됩니다 .


myList = [1, 2, 3, 100, 5]    
sorted(range(len(myList)),key=myList.__getitem__)

[0, 1, 2, 4, 3]

대답 enumerate은 훌륭하지만 개인적으로 값으로 정렬하는 데 사용되는 람다를 좋아하지 않습니다. 다음은 색인과 값을 반대로하여 정렬합니다. 따라서 먼저 값을 기준으로 정렬 한 다음 색인을 기준으로 정렬합니다.

sorted((e,i) for i,e in enumerate(myList))

로 대답을 업데이트 enumerate하고 itemgetter:

sorted(enumerate(a), key=lambda x: x[1])
# [(0, 1), (1, 2), (2, 3), (4, 5), (3, 100)]

목록을 함께 압축하십시오 : 튜플의 첫 번째 요소가 색인이고 두 번째 요소는 값입니다 (그런 다음 튜플의 두 번째 값을 사용하여 정렬하면 x[1]x는 튜플입니다)

또는 모듈 itemgetter에서 사용 operator:

from operator import itemgetter
sorted(enumerate(a), key=itemgetter(1))

numpy를 사용하지 않으려면

sorted(range(len(seq)), key=seq.__getitem__)

여기에 표시된 것처럼 가장 빠릅니다 .


perfplot (내 프로젝트) 으로 이것 에 대한 빠른 성능 검사를 수행 했으며 numpy 이외의 다른 것을 추천하기가 어렵다는 것을 알았습니다 (로그 스케일 참고).

여기에 이미지 설명을 입력하십시오


줄거리를 재현하는 코드 :

import perfplot
import numpy


def sorted_enumerate(seq):
    return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]


def sorted_enumerate_key(seq):
    return [x for x, y in sorted(enumerate(seq), key=lambda x: x[1])]


def sorted_range(seq):
    return sorted(range(len(seq)), key=seq.__getitem__)


def numpy_argsort(x):
    return numpy.argsort(x)


perfplot.save(
    "argsort.png",
    setup=lambda n: numpy.random.rand(n),
    kernels=[sorted_enumerate, sorted_enumerate_key, sorted_range, numpy_argsort],
    n_range=[2 ** k for k in range(15)],
    xlabel="len(x)",
    logx=True,
    logy=True,
)

다른 답변은 잘못되었습니다.

argsort한 번만 실행 하는 것이 해결책이 아닙니다. 예를 들어, 다음 코드는

import numpy as np
x = [3,1,2]
np.argsort(x)

수율 array([1, 2, 0], dtype=int64)우리가 원하는 것이 아니다.

대답은 argsort두 번 실행해야합니다 .

import numpy as np
x = [3,1,2]
np.argsort(np.argsort(x))

array([2, 0, 1], dtype=int64)예상대로 제공합니다 .


기본적으로 argsort외부 라이브러리 (예 : NumPy)를 사용하려는 경우 또는 종속성없이 순수 파이썬을 유지하려는 경우 필요한 구현은에 따라 다릅니다.

스스로에게 물어보아야 할 질문은 다음과 같습니다.

  • indices that would sort the array/list
  • indices that the elements would have in the sorted array/list

Unfortunately the example in the question doesn't make it clear what is desired because both will give the same result:

>>> arr = np.array([1, 2, 3, 100, 5])

>>> np.argsort(np.argsort(arr))
array([0, 1, 2, 4, 3], dtype=int64)

>>> np.argsort(arr)
array([0, 1, 2, 4, 3], dtype=int64)

Choosing the argsort implementation

If you have NumPy at your disposal you can simply use the function numpy.argsort or method numpy.ndarray.argsort.

An implementation without NumPy was mentioned in some other answers already, so I'll just recap the fastest solution according to the benchmark answer here

def argsort(l):
    return sorted(range(len(l)), key=l.__getitem__)

Getting the indices that would sort the array/list

To get the indices that would sort the array/list you can simply call argsort on the array or list. I'm using the NumPy versions here but the Python implementation should give the same results

>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(arr)
array([1, 2, 0, 3], dtype=int64)

The result contains the indices that are needed to get the sorted array.

Since the sorted array would be [1, 2, 3, 4] the argsorted array contains the indices of these elements in the original.

  • The smallest value is 1 and it is at index 1 in the original so the first element of the result is 1.
  • The 2 is at index 2 in the original so the second element of the result is 2.
  • The 3 is at index 0 in the original so the third element of the result is 0.
  • The largest value 4 and it is at index 3 in the original so the last element of the result is 3.

Getting the indices that the elements would have in the sorted array/list

In this case you would need to apply argsort twice:

>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(np.argsort(arr))
array([2, 0, 1, 3], dtype=int64)

In this case :

  • the first element of the original is 3, which is the third largest value so it would have index 2 in the sorted array/list so the first element is 2.
  • the second element of the original is 1, which is the smallest value so it would have index 0 in the sorted array/list so the second element is 0.
  • the third element of the original is 2, which is the second-smallest value so it would have index 1 in the sorted array/list so the third element is 1.
  • the fourth element of the original is 4 which is the largest value so it would have index 3 in the sorted array/list so the last element is 3.

Import numpy as np

색인

S=[11,2,44,55,66,0,10,3,33]

r=np.argsort(S)

[output]=array([5, 1, 7, 6, 0, 8, 2, 3, 4])

argsort S의 인덱스를 정렬 된 순서로 반환

가치를 위해

np.sort(S)

[output]=array([ 0,  2,  3, 10, 11, 33, 44, 55, 66])

0에서 n-1 사이의 다른 인덱스 배열을 만든 다음 이것을 원래 배열로 압축 한 다음 원래 값을 기준으로 정렬합니다

ar = [1,2,3,4,5]
new_ar = list(zip(ar,[i for i in range(len(ar))]))
new_ar.sort()

`

참고 URL : https://stackoverflow.com/questions/6422700/how-to-get-indices-of-a-sorted-array-in-python

반응형