在基本 Python 中等效于 Numpy.argsort() ?

Python 是否有一个内置的函数,它在 python.array上做的事情和 argsort()numpy.array上做的事情一样?

54939 次浏览

虽然没有内置函数,但是可以很容易地用 Python 提供的极好的工具组装一个函数:

def argsort(seq):
# http://stackoverflow.com/questions/3071415/efficient-method-to-calculate-the-rank-vector-of-a-list-in-python
return sorted(range(len(seq)), key=seq.__getitem__)


x = [5,2,1,10]


print(argsort(x))
# [2, 1, 0, 3]

它在 Python array.array上的工作方式与此相同:

import array
x = array.array('d', [5, 2, 1, 10])
print(argsort(x))
# [2, 1, 0, 3]

我的选择是列举:

def argsort(seq):
return [x for x,y in sorted(enumerate(seq), key = lambda x: x[1])]


seq=[5,2,1,10]
print(argsort(seq))
# Output:
# [2, 1, 0, 3]

不过最好使用来自 https://stackoverflow.com/users/9990/marcelo-cantos的答案来回答线程 没有 lambda 表达式的 python 排序

[i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]

我计算了上述建议的时间,以下是我的结果。

import timeit
import random
import numpy as np


def f(seq):
# http://stackoverflow.com/questions/3382352/equivalent-of-numpy-argsort-in-basic-python/3383106#3383106
#non-lambda version by Tony Veijalainen
return [i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]


def g(seq):
# http://stackoverflow.com/questions/3382352/equivalent-of-numpy-argsort-in-basic-python/3383106#3383106
#lambda version by Tony Veijalainen
return [x for x,y in sorted(enumerate(seq), key = lambda x: x[1])]




def h(seq):
#http://stackoverflow.com/questions/3382352/equivalent-of-numpy-argsort-in-basic-python/3382369#3382369
#by unutbu
return sorted(range(len(seq)), key=seq.__getitem__)




seq = list(range(10000))
random.shuffle(seq)


n_trials = 100
for cmd in [
'f(seq)', 'g(seq)', 'h(seq)', 'np.argsort(seq)',
'np.argsort(seq).tolist()'
]:
t = timeit.Timer(cmd, globals={**globals(), **locals()})
print('time for {:d}x {:}: {:.6f}'.format(n_trials, cmd, t.timeit(n_trials)))

输出

time for 100x f(seq): 0.323915
time for 100x g(seq): 0.235183
time for 100x h(seq): 0.132787
time for 100x np.argsort(seq): 0.091086
time for 100x np.argsort(seq).tolist(): 0.104226

给出了一个与问题大小相关的 给你分析。

找到了这个问题,但是需要基于对象属性的对象列表的 argsort。

扩展 unutbu 的回答,这将是:

sorted(range(len(seq)), key = lambda x: seq[x].sort_property)