is there a builtin function of Python that does on python.array what argsort() does on a numpy.array?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
There is no built-in function, but it’s easy to assemble one out of the terrific tools Python makes available:
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]
It works on Python array.arrays the same way:
import array
x = array.array('d', [5, 2, 1, 10])
print(argsort(x))
# [2, 1, 0, 3]
Method 2
I timed the suggestions above and here are my results.
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)))
output
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
A problem size dependent analysis is given here.
Method 3
My alternative with enumerate:
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]
Better though to use answer from https://stackoverflow.com/users/9990/marcelo-cantos answer to thread python sort without lambda expressions
[i for (v, i) in sorted((v, i) for (i, v) in enumerate(seq))]
Method 4
Found this question, but needed argsort for a list of objects based on an object property.
Extending unutbu’s answer, this would be:
sorted(range(len(seq)), key = lambda x: seq[x].sort_property)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0