Equivalent of Numpy.argsort() in basic python?

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

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x