在python的numpy包中,有一个函数叫sort,给一个列表进行排序;也有一个函数叫argsort,给出排序后的列表中的每一个元素在原列表中的索引值。该函数的详细介绍见https://numpy.org/doc/stable/reference/generated/numpy.argsort.html
例如,以下代码:
import numpy as np
arrayNumber = [4,1,6,2,9,0]
arraySort = np.sort(arrayNumber)
print("Sorted array is %s"%arraySort)
arrayArgSort = np.argsort(arrayNumber)
print("Argsorted array is %s"%arrayArgSort)
输出的结果为
因为在排序后的列表arraySort中,第1个元素0是原列表中索引为5的元素(Python的索引值是从0开始),第2个元素1是原列表中索引为1的元素,第3个元素2是原列表中索引为3的元素,以此类推,所以arrayArgSort表示arraySort的每个元素是原列表arrayNumber中哪个索引号的元素。换言之,arrayNumber[arrayArgSort[k]]=arraySort[k]。
用argsort函数计算每个元素的排名
如何用argsort函数快速计算出arrayNumber中每一个元素在列表中的排名?通过实验,发现只需对argsort函数进行一次嵌套调用即可
arrayRank = np.argsort(arrayArgSort)
print("Rank of the each element of the array is %s"%arrayRank)
输出的结果为[3, 1, 4, 2, 5, 0]。若把排名从0开始计,0表示最小元素,5表示最大元素,则输出的结果符合正确排名。
例如,原列表的元素6排名为4,也就是第5小的元素。
能计算出排名的原因
下面说明这个算法能正确计算出排名的原因及证明。
假设列表A通过argsort函数转换为列表B,即B=np.argsort(A),则如果元素A[y]在A中排名为x,那么B[x]=y (1)
同样,D=np.argsort(B),那么如果B[x]在B中排名为z,那么D[z]=x (2)
由于B是一个索引值列表,如果A的长度为n,则B里的元素只有0,1,2,...,n-1。
因此,B中排名为z的元素,就是z,即B[x]=z (3)
因此,把(3)代入(2),可得D[B[x]]=x (4)
同时把(1)代入(4),可得D[y]=x,问题得证。A[y]在A中排名为x,则D[y]=x。D中的每个元素,就是A中每个元素在A中的排名。