Numpy argsort - 它在做什么?

use*_*273 105 python numpy

为什么numpy给出了这个结果:

x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()

>[2 3 1 0]
Run Code Online (Sandbox Code Playgroud)

当我希望它能做到这一点时:

[3 2 0 1]

显然我对这个功能的理解是缺乏的.

fal*_*tru 121

根据文件

返回对数组进行排序的索引.

  • 2是指数0.0.
  • 3是指数0.1.
  • 1是指数1.41.
  • 0是指数1.48.

  • `a = x.argsort()`,print`x [a]`,我们将得到`array([0.,0.1,1.41,1.48])` (9认同)

unu*_*tbu 35

[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
Run Code Online (Sandbox Code Playgroud)

例如,

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])
Run Code Online (Sandbox Code Playgroud)

这会检查它们是否都产生相同的结果:

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))
Run Code Online (Sandbox Code Playgroud)

这些IPython %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
Run Code Online (Sandbox Code Playgroud)

对于小型阵列,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
Run Code Online (Sandbox Code Playgroud)

另请注意,这stats.rankdata使您可以更好地控制如何处理相等值的元素.

  • 您能否添加一些解释,解释为什么应用 argsort() 两次可以得出排名? (2认同)
  • @Phani:“argsort”返回排序数组的索引。排序后的索引的索引就是排名。这是第二次调用“argsort”返回的结果。 (2认同)
  • 第一个argsort返回一个排列(如果应用于数据将对其进行排序).当argsort应用于(this或任何)置换时,它返回逆置换(如果2个置换以任一顺序相互应用,则结果为Identity).如果应用于排序数据数组,则第二个排列将产生未排序的数据数组,即它是排名. (2认同)
  • 脑洞大开。我终于明白了!它返回一个数组,其内容是按排序顺序的原始数组的索引。 (2认同)