155

为什么 numpy 给出这个结果:

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

>[2 3 1 0]

当我期望它这样做时:

[3 2 0 1]

显然我对函数的理解不足。

4

10 回答 10

165

根据文档

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

  • 2是 的索引0.0
  • 3是 的索引0.1
  • 1是 的索引1.41
  • 0是 的索引1.48
于 2013-07-27T18:48:07.930 回答
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基准测试表明大型数组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使您可以更好地控制如何处理等值元素。

于 2013-07-27T18:47:52.837 回答
4

正如文档所说,argsort

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

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

您似乎想要的是值的排名顺序,这是由scipy.stats.rankdata. 请注意,您需要考虑如果队伍中有平局会发生什么。

于 2013-07-27T18:48:07.037 回答
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/generated/numpy.argsort.html

于 2019-01-17T10:10:32.413 回答
1

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

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

于 2018-02-18T01:50:11.650 回答
0

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

[2,3,1,0]
于 2019-10-17T15:37:38.527 回答
0

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

于 2018-07-22T08:47:18.020 回答
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),此答案仅用于说明目的。

于 2017-11-17T07:33:27.510 回答
0

首先,它被排序为数组。然后用数组的初始索引生成一个数组。

于 2017-06-27T01:27:27.490 回答
0

对于任何想知道“为什么使用 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 个最高薪人的姓名。

于 2021-11-05T03:38:54.770 回答