숫자 목록이 있습니다.
myList = [1, 2, 3, 100, 5]
이제이 목록을 정렬하면 얻을 수 [1, 2, 3, 5, 100]
있습니다. 내가 원하는 것은 정렬 된 순서대로 원래 목록의 요소 인덱스입니다. 즉 [0, 1, 2, 4, 3]
, 값과 인덱스를 모두 반환하는 ala MATLAB의 정렬 함수입니다.
숫자 목록이 있습니다.
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 ...]
목록 이해를 사용하여 추출됩니다 .
itemgetter(1)
람다 함수 대신 사용할 수 있습니다
sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
x = [3,1,2]; numpy.argsort(x)
[1,2,0].
myList = [1, 2, 3, 100, 5]
sorted(range(len(myList)),key=myList.__getitem__)
[0, 1, 2, 4, 3]
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))
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)",
)
기본적으로 argsort
외부 라이브러리 (예 : NumPy)를 사용하려는 경우 또는 의존하지 않고 순수한 파이썬을 유지하려는 경우 필요한 구현이 필요합니다.
스스로에게 물어보아야 할 질문은 다음과 같습니다.
불행히도 문제의 예는 원하는 결과를 명확하게 나타내지 못합니다.
>>> 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)
argsort
구현NumPy를 마음대로 사용할 수 있다면 단순히 함수 numpy.argsort
또는 방법을 사용할 수 있습니다numpy.ndarray.argsort
.
NumPy가없는 구현은 이미 다른 답변에서 언급되었으므로 벤치 마크 답변 에 따라 가장 빠른 솔루션을 요약 해 보겠습니다 .
def argsort(l):
return sorted(range(len(l)), key=l.__getitem__)
배열 / 목록을 정렬하는 인덱스를 얻으려면 간단히 argsort
배열 또는 목록을 호출 하면됩니다. 여기 NumPy 버전을 사용하고 있지만 Python 구현은 동일한 결과를 제공해야합니다
>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(arr)
array([1, 2, 0, 3], dtype=int64)
결과에는 정렬 된 배열을 얻는 데 필요한 인덱스가 포함됩니다.
정렬 된 배열은 [1, 2, 3, 4]
argsorted 배열이므로 원본에 이러한 요소의 인덱스가 포함됩니다.
1
색인 1
에 있으므로 결과의 첫 번째 요소는 1
입니다.2
인덱스이며 2
결과의 두 번째 요소는 그래서 일본어로 2
.3
인덱스이며 0
결과의 세번째 요소는 그래서 일본어로 0
.4
이며 3
원본의 색인 에 있으므로 결과의 마지막 요소는 3
입니다.이 경우 argsort
두 번 적용해야합니다 .
>>> arr = np.array([3, 1, 2, 4])
>>> np.argsort(np.argsort(arr))
array([2, 0, 1, 3], dtype=int64)
이 경우 :
3
세 번째로 큰 값이므로 2
정렬 된 배열 / 목록에 색인 이 있으므로 첫 번째 요소는2
입니다.1
가장 작은 값이므로 0
정렬 된 배열 / 목록에 색인 이 있으므로 두 번째 요소는 0
입니다.2
는, 두 번째로 작은 값이므로 1
정렬 된 배열 / 목록에 인덱스 가 있으므로 세 번째 요소는 1
입니다.4
가장 큰 값이므로 3
정렬 된 배열 / 목록에 색인 이 있으므로 마지막 요소는 3
입니다.다른 답변은 잘못되었습니다.
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)
예상대로 제공합니다 .
x[2]
(3) 가장 작은 요소와 x[1]
(1) 가장 큰 요소입니다 (정수를 정렬하면 가장 작은 값에서 가장 큰 값으로 정렬되므로). 또한 OPs 예제에서 단일 np.argsort([1, 2, 3, 100, 5])
수익률 array([0, 1, 2, 4, 3])
은 OP가 원하는 인덱스로 나타납니다.
arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
가 달리면 [0 1 2 4 5 3]
어느 것이 잘못되었는지 알게 됩니다.
arr[res]
yields array([ 1, 2, 3, 5, 9, 100])
는 결과 배열이 (증가하는) 순서이기 때문에 완벽하게 괜찮은 것처럼 보인다.
arr=[1,2,3,100, 5, 9]
경우 출력이이라고 예상합니다 inds=[0,1,2,5,3,4]
. 왜냐하면 요소를 주문하는 순서 (증가)-1은 0, 2는 1, ..., 5는 4 위, 3 위, 9 위 그 출력 ( inds
) 을 얻으려면 argsort
언급 한 것처럼 두 번 실행해야합니다 .
sort
대한 OP의 언급을 감안할 때 OP np.argsort
는 일반적으로 사용되는 것과 비슷한 다른 기능을 원한다고 생각합니다 ( arr[np.argsort[arr]]
마지막 MATLAB 예제에서와 같이 정렬 된 배열을 얻는 데 사용할 수 있음 ). 귀하의 답변 이 대신 이 사례 / 질문에 적용됩니다 .