【发布时间】:2011-03-23 21:06:43
【问题描述】:
是否有 Python 的内置函数在 python.array 上执行 argsort() 在 numpy.array 上的作用?
【问题讨论】:
是否有 Python 的内置函数在 python.array 上执行 argsort() 在 numpy.array 上的作用?
【问题讨论】:
我对上面的建议进行了计时,这是我的结果。
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
问题大小相关分析给出here。
【讨论】:
%timeit 报告了 3 个平均 100 个循环中的最佳平均值。
没有内置函数,但很容易从 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.arrays:
import array
x = array.array('d', [5, 2, 1, 10])
print(argsort(x))
# [2, 1, 0, 3]
【讨论】:
operator.itemgetter / operator.attrgetter docs.python.org/library/operator.html
operator.itemgetter 可以用作__getitem__ 的替代品,我想我同意你的看法,但据我所知,operator.itemgetter 也需要将其包装在 lambda 表达式中。如果可以的话,我宁愿避免使用额外的lambda。
itemgetter 在这里没有用处:x.__getitem__(i) 返回x[i],而itemgetter(x)(i) 将返回i[x]。
找到了这个问题,但需要 argsort 来获取基于对象属性的对象列表。
扩展 unutbu 的答案,这将是:
sorted(range(len(seq)), key = lambda x: seq[x].sort_property)
【讨论】:
我的枚举替代方案:
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 的回答来回答线程python sort without lambda expressions
[i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]
【讨论】: