Numpy argsort – 它在做什么?
为什么numpy给出这个结果:
x = numpy.array([1.48,1.41,0.0,0.1]) print x.argsort() >[2 3 1 0]
当我期望它做到这一点时:
[3 2 0 1]
显然我对这个function的理解是缺乏的。
根据文件
返回将sorting数组的索引。
-
2
是0.0
的指数。 -
3
是0.1
的指数。 -
1
是1.41
的指数。 -
0
是1.48
的指数。
[2, 3, 1, 0]
指示最小的元素在索引2处,在索引3处接下来最小,然后是索引1,然后是索引0。
有很多方法可以得到您要查找的结果:
import numpy as np import scipy.stats as stats def using_indexed_assignment(x): "https://stackoverflow.com/a/5284703/190597 (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://stackoverflow.com/a/6266510/190597 (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))
这些IPython %timeit
基准testing表明,对于大型数组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
:
返回将sorting数组的索引。
这意味着argsort的第一个元素是应该首先sorting的元素的索引,第二个元素是第二个元素的索引等等。
你似乎想要的是价值的排名顺序,这是由scipy.stats.rankdata
提供的。 请注意,如果队伍中存在联系,则需要考虑会发生什么情况。
首先,它是有序的arrays。 然后用数组的初始索引生成一个数组。
只是想直接对比OP的原始理解和代码的实际实现。
numpy.argsort
是这样定义的
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
OP本来认为是这样定义的
x == numpy.sort(x)[x.argsort()] # this will not be True