Numpy argsort-它在做什么?


123

为什么numpy给出以下结果:

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

>[2 3 1 0]

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

[3 2 0 1]

显然,我对该功能缺乏了解。


6
您为什么认为[3 2 0 1]应该是正确的答案?
zwol

9
我只是对输出有相反的理解。也就是说,如果采用x的第一个元素,则它应位于已排序数组的位置3,依此类推。
user1276273 2013年

26
您的思维方式完全有道理,我有完全相同的问题
adrienlucca.wordpress.com

2
[3 2 0 1]-这是对值进行排名,您没有得到实际的索引。
Lahiru Karunaratne

只是要记住,当您认为输出在已排序的数组中时,输出会指示原始数组中的位置。这意味着output [0]是原始输入数组中最小元素所在的索引,最大元素的output [-1]。
lincr

Answers:


143

根据文档

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

  • 2是的索引0.0
  • 3是的索引0.1
  • 1是的索引1.41
  • 0是的索引1.48

12
a = x.argsort(),打印x[a],我们会得到array([ 0. , 0.1 , 1.41, 1.48])
贝尔德

39

[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基准测试建议大型阵列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使您可以更好地控制如何处理相等值的元素。


1
您能否添加一些解释,为什么两次应用argsort()会给我们排名?
帕尼(Pani)2014年

1
@Phani:argsort返回已排序数组的索引。排序索引的索引是等级。这是第二次调用argsort返回的内容。
unutbu 2014年

2
第一个argsort返回一个排列(如果将其应用于数据将对其进行排序)。将argsort应用于(此或任何)置换时,它返回反向置换(如果将2个置换以任意顺序应用于彼此,则结果为Identity)。如果将第二个置换应用于已排序的数据数组,则会产生未排序的数据数组,即它是等级。
亚历克斯·C

1
精神震撼。我终于明白了!它返回一个数组,其内容是按排序顺序的原始数组的索引。
何塞A

3

由于文档说,argsort

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

这意味着argsort的第一个元素是应首先排序的元素的索引,第二个元素是应第二个排序的元素的索引,依此类推。

您似乎想要的是值的排名顺序,这是由提供的scipy.stats.rankdata。请注意,如果队伍中有平局,您需要考虑应该怎么做。


3

numpy.argsort(a,axis = -1,kind ='quicksort',order = None)

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

使用kind关键字指定的算法沿给定的轴执行间接排序。它沿着给定的轴按排序顺序返回与该索引数据具有相同形状的索引数组。

考虑一下python中的一个示例,其中包含一个值列表

listExample  = [0 , 2, 2456,  2000, 5000, 0, 1]

现在我们使用argsort函数:

import numpy as np
list(np.argsort(listExample))

输出将是

[0, 5, 6, 1, 3, 2, 4]

这是listExample中值索引的列表,如果将这些索引映射到各自的值,则将得到如下结果:

[0, 0, 1, 2, 2000, 2456, 5000]

(我发现此功能在许多地方都非常有用,例如,如果您想对列表/数组进行排序,但又不想使用list.sort()函数(即,不更改列表中实际值的顺序),则可以使用此功能功能。)

有关更多详细信息,请参见以下链接:https : //docs.scipy.org/doc/numpy-1.15.0/reference/genic/numpy.argsort.html


1

输入:
将numpy导入为np
x = np.array([1.48,1.41,0.0,0.1])
x.argsort()。argsort()

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


1
尽管此代码段可能是解决方案,但包括说明确实有助于提高帖子的质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
Peacetype '18


0

np.argsort返回“种类”(指定排序算法的类型)给定的排序数组的索引。但是,当列表与np.argmax一起使用时,它将返回列表中最大元素的索引。而np.sort对给定的数组,列表进行排序。


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

注意:此代码在一般情况下不起作用(仅适用于1D),此答案仅用于说明目的。


x[x.argsort()]不一定与相同np.sort(x)。实际上,形状不一定相同。尝试使用2D阵列。这仅适用于一维阵列。
内森

我觉得那是不必要的书呆子。问题是关于一维数组。这旨在作为一种理解差异的方法,而不是使用文字代码。此外,当您拥有2D阵列时,甚至无法确定所需的排序类型。您是否需要全局排序?如果不是,应该对哪个轴排序?无论如何,我添加了免责声明。
Multihunter

0

它根据给定的数组索引返回索引[1.48,1.41,0.0,0.1],这意味着: 0.0是索引[2]中的第一个元素。 0.1是index [3]中的第二个元素。 1.41是索引[1]中的第三个元素。 1.48是索引[0]中的第四个元素。输出:

[2,3,1,0]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.