IT story

내림차순으로 argsort를 사용할 수 있습니까?

hot-time 2020. 6. 13. 09:45
반응형

내림차순으로 argsort를 사용할 수 있습니까?


다음 코드를 고려하십시오.

avgDists = np.array([1, 8, 6, 9, 4])
ids = avgDists.argsort()[:n]

이것은 나에게 n가장 작은 요소의 지표를 제공 합니다. 가장 높은 원소 argsort의 인덱스를 얻기 위해 이것을 내림차순 으로 사용할 n있습니까?


배열을 부정하면 가장 낮은 요소가 가장 높은 요소가되고 그 반대도 마찬가지입니다. 따라서 n가장 높은 요소 의 지수는 다음 과 같습니다.

(-avgDists).argsort()[:n]

의견 에서 언급했듯이 이것에 대해 추론하는 또 다른 방법 은 큰 요소가 argsort 에서 마지막오는 것을 관찰하는 것입니다. 따라서 argsort의 꼬리에서 읽어 n가장 높은 요소 를 찾을 수 있습니다.

avgDists.argsort()[::-1][:n]

두 방법 모두 시간 복잡성에서 O (n log n) 입니다 argsort. 여기서 호출은 지배적 인 용어 이기 때문 입니다. 그러나 두 번째 접근 방식은 배열 O (n) 부정을 O (1) 슬라이스로 대체합니다 . 루프 내부의 작은 배열로 작업하는 경우 해당 부정을 피함으로써 성능이 약간 향상 될 수 있으며, 큰 배열로 작업하는 경우 부정이 전체 배열의 복사본을 생성하므로 메모리 사용량을 절약 할 수 있습니다.

이러한 메소드가 항상 동등한 결과를 제공하지는 않습니다. argsort예를 들어 키워드 인수를 전달하여 안정적인 정렬 구현이 요청 된 kind='mergesort'경우 첫 번째 전략은 정렬 안정성을 유지하지만 두 번째 전략은 안정성을 잃습니다 (예 : 항목이 반전됩니다).


그냥 파이썬과 같은, 즉에 [::-1]의해 반환 된 배열을 반전 argsort()하고 [:n]마지막 n 개의 요소를 제공합니다 :

>>> avgDists=np.array([1, 8, 6, 9, 4])
>>> n=3
>>> ids = avgDists.argsort()[::-1][:n]
>>> ids
array([3, 1, 2])

이 방법의 장점은 avgDists ids관점 입니다.

>>> ids.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

( '거짓'인 'OWNDATA'는 이것이 사본이 아니라보기임을 나타냅니다)

이를 수행하는 다른 방법은 다음과 같습니다.

(-avgDists).argsort()[:n]

문제는 이것이 작동하는 방식이 배열의 각 요소에 대해 음수를 만드는 것입니다.

>>> (-avgDists)
array([-1, -8, -6, -9, -4])

ANd는이를 위해 사본을 작성합니다.

>>> (-avgDists_n).flags['OWNDATA']
True

따라서 매우 작은 데이터 세트로도 시간을 정할 경우 :

>>> import timeit
>>> timeit.timeit('(-avgDists).argsort()[:3]', setup="from __main__ import avgDists")
4.2879798610229045
>>> timeit.timeit('avgDists.argsort()[::-1][:3]', setup="from __main__ import avgDists")
2.8372560259886086

보기 방법이 훨씬 빠릅니다


당신은 플립 명령을 사용할 수 있습니다 numpy.flipud()또는 numpy.fliplr()사용하여 정렬 한 후 내림차순으로 인덱스를 얻기 위해 argsort명령을 사용합니다. 그게 내가 보통하는 일입니다.


가장 낮은 / 가장 높은 n 요소의 인덱스 만 필요한 경우 np.argsort사용 하는 대신 사용할 수 있습니다 np.argpartition.

전체 배열을 정렬 할 필요는 없지만 필요한 부분 만 정렬 할 필요가 있지만 "파티션 내부의 순서"는 정의되어 있지 않으므로 올바른 인덱스를 제공하지만 올바르게 정렬되지 않을 수 있습니다.

>>> avgDists = [1, 8, 6, 9, 4]
>>> np.array(avgDists).argpartition(2)[:2]  # indices of lowest 2 items
array([0, 4], dtype=int64)

>>> np.array(avgDists).argpartition(-2)[-2:]  # indices of highest 2 items
array([1, 3], dtype=int64)

You could create a copy of the array and then multiply each element with -1.
As an effect the before largest elements would become the smallest.
The indeces of the n smallest elements in the copy are the n greatest elements in the original.


With your example:

avgDists = np.array([1, 8, 6, 9, 4])

Obtain indexes of n maximal values:

ids = np.argpartition(avgDists, -n)[-n:]

Sort them in descending order:

ids = ids[np.argsort(avgDists[ids])[::-1]]

Obtain results (for n=4):

>>> avgDists[ids]
array([9, 8, 6, 4])

As @Kanmani hinted, an easier to interpret implementation may use numpy.flip, as in the following:

import numpy as np

avgDists = np.array([1, 8, 6, 9, 4])
ids = np.flip(np.argsort(avgDists))
print(ids)

By using the visitor pattern rather than member functions, it is easier to read the order of operations.


Another way is to use only a '-' in the argument for argsort as in : "df[np.argsort(-df[:, 0])]", provided df is the dataframe and you want to sort it by the first column (represented by the column number '0'). Change the column-name as appropriate. Of course, the column has to be a numeric one.


A simple way is to take absolute values and add a negative sign to each element then do argsort.

l=np.array([1,-1,2])
print(np.argsort((-np.abs(x))))  #[2,1,0]

참고URL : https://stackoverflow.com/questions/16486252/is-it-possible-to-use-argsort-in-descending-order

반응형