Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

argsort gives wrong results #8757

Closed
marcocaccin opened this issue Mar 8, 2017 · 4 comments
Closed

argsort gives wrong results #8757

marcocaccin opened this issue Mar 8, 2017 · 4 comments

Comments

@marcocaccin
Copy link

marcocaccin commented Mar 8, 2017

The argsort function seems to be broken. Looking at the code provided, the argsort for rows [0, 1] is correct but it's messed up for rows [2, 3].
I tested this on different NumPy installations and versions 1.11.0 and 1.12.0

import numpy as np

vec = np.array([
    [-1.4, -1.2,  1.3],
    [-3.6,  3.9, -3.7],
    [-2.3,  1.5, -2. ],
    [-2.6,  2.4, -1.6]
    ])

In [1]: np.argsort(-vec, axis=1)
Out[1]: 
array([[2, 1, 0],
       [1, 0, 2],
       [1, 2, 0],
       [1, 2, 0]])
@seberg
Copy link
Member

seberg commented Mar 8, 2017

Can't see anything wrong with the result, print out vec[np.arange(4)[:, np.newaxis], np.argsort(-vec, axis=1)] and see that it looks good.

@ghost
Copy link

ghost commented Jan 3, 2018

This is the second google result for "np argsort wrong".

The explanation on the docs page is unclear (to me). I will add my own explanation here in the hopes that it helps someone:

x = numpy.array([1.48,1.31,0.0,0.8])
print x.argsort()

>[2 3 1 0]

Some people might expect this to instead give [3, 2, 0, 1], i.e., the 0th element in the unsorted array should be the 3rd element in the sorted array.

What it actually does is provide indices such that x[np.argsort(x)] will give you a sorted list, i.e., [0.0, 0.8, 1.31, 1.48]. Put another way, [2 3 1 0] tells you that the 0th element of the sorted array is the 2nd element of the unsorted array.

If you really want to get [3, 2, 0, 1] as an output, you can instead do

np.argsort(np.argsort(x))
>[3 2 0 1]

Alternatively, if you're just really off-base like I was and only want, say, the indices of the 3 largest elements in x:

np.argsort(x)[:-4:-1]
>[0, 1, 3]

@eric-wieser
Copy link
Member

eric-wieser commented Jan 3, 2018

If you really want to get [3, 2, 0, 1] as an output, you can instead do

Doing this will be faster:

a = np.empty(len(x), np.intp)
a[np.argsort(x)] = np.arange(len(x))

#9880 suggests adding this to numpy as np.invert_permutation(np.argsort(x))

@eric-wieser
Copy link
Member

eric-wieser commented Oct 14, 2020

@rossbar, @bjnath: Perhaps worth extracting stuff from @ghost's comment above and putting it in the docs? I've added some more crosslinks to show more examples of confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants