为什么numpy会给出这个结果:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
我本期望它做到这一点:
[3 2 0 1]
显然,我对函数的理解不够。
a = x.argsort()
, print x[a]
, we will get array([ 0. , 0.1 , 1.41, 1.48])
- Belter[2, 3, 1, 0]
表示最小元素的索引为2,其次是索引3、1和0。
有许多方法可以得到您要查找的结果:
import numpy as np
import scipy.stats as stats
def using_indexed_assignment(x):
"https://dev59.com/WsKVzogBFxS5KdRj5vjM#5284703 (Sven Marnach)"
result = np.empty(len(x), dtype=int)
temp = x.argsort()
result[temp] = np.arange(len(x))
return result
def using_rankdata(x):
return stats.rankdata(x)-1
def using_argsort_twice(x):
"https://dev59.com/WsKVzogBFxS5KdRj5vjM#6266510 (k.rooijers)"
return np.argsort(np.argsort(x))
def using_digitize(x):
unique_vals, index = np.unique(x, return_inverse=True)
return np.digitize(x, bins=unique_vals) - 1
In [72]: x = np.array([1.48,1.41,0.0,0.1])
In [73]: using_indexed_assignment(x)
Out[73]: array([3, 2, 0, 1])
这将检查它们是否都产生相同的结果:
x = np.random.random(10**5)
expected = using_indexed_assignment(x)
for func in (using_argsort_twice, using_digitize, using_rankdata):
assert np.allclose(expected, func(x))
%timeit
基准测试表明,对于大型数组,using_indexed_assignment
是最快的。In [50]: x = np.random.random(10**5)
In [66]: %timeit using_indexed_assignment(x)
100 loops, best of 3: 9.32 ms per loop
In [70]: %timeit using_rankdata(x)
100 loops, best of 3: 10.6 ms per loop
In [56]: %timeit using_argsort_twice(x)
100 loops, best of 3: 16.2 ms per loop
In [59]: %timeit using_digitize(x)
10 loops, best of 3: 27 ms per loop
对于小数组,using_argsort_twice
可能更快:
In [78]: x = np.random.random(10**2)
In [81]: %timeit using_argsort_twice(x)
100000 loops, best of 3: 3.45 µs per loop
In [79]: %timeit using_indexed_assignment(x)
100000 loops, best of 3: 4.78 µs per loop
In [80]: %timeit using_rankdata(x)
100000 loops, best of 3: 19 µs per loop
In [82]: %timeit using_digitize(x)
10000 loops, best of 3: 26.2 µs per loop
stats.rankdata
可以更好地控制如何处理相等值的元素。argsort
返回已排序数组的索引。已排序索引的索引是排名。这就是第二次调用 argsort
返回的内容。 - unutbuargsort
:返回数组排序后的索引。这意味着argsort的第一个元素是应该被排序的第一个元素的索引,第二个元素是应该排在第二位的元素的索引,以此类推。您似乎想要的是值的等级顺序,这正是scipy.stats.rankdata
提供的。请注意,如果排名相同,您需要考虑应该发生什么情况。numpy.argsort(a, axis=-1, kind='quicksort', order=None)
返回一个数组排序后的下标。
在给定轴上使用kind关键字指定的算法执行间接排序。它返回一个与该索引数据形状相同的数组,按排序顺序沿着给定轴的索引。
例如,在Python中有一个值列表
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
import numpy as np
list(np.argsort(listExample))
[0, 5, 6, 1, 3, 2, 4]
[0, 0, 1, 2, 2000, 2456, 5000]
如果有人想知道“为什么要argsort”,我的答案是“使用一个数组来对另一个数组进行排序”:
In [49]: a = np.array(list('asdf'))
In [50]: b = [3,2,0,1]
In [51]: np.argsort(b)
Out[51]: array([2, 3, 1, 0])
In [52]: a[np.argsort(b)]
Out[52]: array(['d', 'f', 's', 'a'], dtype='<U1')
这对于列数据非常有用,例如一个名字列和一个薪水列,你想看到N个最高薪水的人的名字。
输入:
import numpy as np
x = np.array([1.48,1.41,0.0,0.1])
x.argsort().argsort()
输出:
array([3, 2, 0, 1])
只是想通过代码直接对比原帖作者的理解与实际实现。
numpy.argsort
的定义是针对一维数组的:
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
原帖作者最初认为它的定义是针对一维数组的:
x == numpy.sort(x)[x.argsort()] # this will not be True
注意:此代码不适用于一般情况(只适用于1D),此答案仅供说明目的。
x[x.argsort()]
不一定等同于 np.sort(x)
。实际上,它们的形状甚至不一定相同。使用 2D 数组尝试一下就知道了。这只适用于 1D 数组。 - Nathannp.argsort返回由“kind”(指定排序算法类型)给出的排序数组的索引。然而,当使用np.argmax时,如果使用列表,则返回列表中最大元素的索引。而np.sort则对给定的数组或列表进行排序。
首先,对数组进行排序。然后生成一个以数组初始索引为基础的新数组。
根据给定的数组索引[1.48,1.41,0.0,0.1]
,它返回相应的索引,即:
0.0
是第一个元素,在索引[2]处。
0.1
是第二个元素,在索引[3]处。
1.41
是第三个元素,在索引[1]处。
1.48
是第四个元素,在索引[0]处。
输出:
[2,3,1,0]
[3 2 0 1]
是正确答案? - zwol