2013-07-27 48 views
63

为什么numpy的给这个结果:Numpy argsort - 它在做什么?

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

>[2 3 1 0] 

时,我希望它这样做:

[3 2 0 1]

显然我对功能的认识是缺乏。

+2

为什么你认为'[3 2 0 1]'本来正确的答案? – zwol

+6

我刚刚对输出有了一个相反的理解。也就是说,如果你把x的第一个元素,它应该在排序数组的位置3,依此类推。 – user1276273

+11

你的思维方式完全是有道理的,我有完全一样的问题 –

回答

67

根据the documentation

返回对数组排序的索引。

  • 20.0索引。
  • 30.1的索引。
  • 11.41索引。
  • 01.48索引。
+3

'A = x.argsort()','打印X [A]',我们将获得'阵列([0,0.1,1.41,1.48)' – Belter

21

[2, 3, 1, 0]指出最小的元素的索引为2,下一个最小的指数3,那么指数1,那么指数为0。

a number of ways得到的结果您正在寻找:

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基准提出了大型阵列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可让您更好地控制如何处理同等价值的元素。

+0

你能否添加一些解释为什么应用argsort()两次给了我们等级? – Phani

+0

@Phani:'argsort'返回排序数组的索引。排序指数的指数是排名。这是第二次调用'argsort'返回的内容。 – unutbu

+2

第一个参数返回一个置换(如果应用于数据将对其进行排序)。当将argsort应用于(此或任何)置换时,它将返回逆置换(如果以任一顺序将2个置换应用于对方,则结果为身份)。如果应用于排序数据数组,则第二置换将产生未排序数据数组,即它是排名。 –

2

由于the documentation说,argsort

返回对数组排序的索引。

这意味着argsort的第一个元素是应该先排序元素的索引,第二个因素是,应该是第二个元素的索引等

你似乎什么想要的是价值的等级顺序,这是由scipy.stats.rankdata提供的。请注意,如果队伍中存在关系,你需要考虑应该发生什么。

+0

是的 - 谢谢。这就是我认为它应该给予的结果。它的工作方式对我的使用来说是完全正常的,我只是不理解它。没有足够的咖啡也许...... – user1276273

0

首先,它被下令阵列。然后用数组的初始索引生成一个数组。

+0

请重复性代码回答 –

0

只想直接对比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 
0

输入:
进口numpy的作为NP
X = np.array([ 1.48,1.41,0.0,0.1])
x.argsort()。argsort()

输出:
阵列([3,2,0,1])

+0

虽然这个代码片断可能是解决方案,[包括说明](// meta.stackexchange.com/questions/114762/explaining-entirely-代码为基础的答案)确实有助于提高您的文章质量。请记住,您将来会为读者回答问题,而这些人可能不知道您的代码建议的原因。 – peacetype