You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently, in order to sort an array in reverse order you have to use some form of strange hack, which may or may not be guaranteed to work in the future.
I suggest adding a reverse parameter to np.sort, similar to the native Python sort() function. This would make the hacks unnecessary and improve readability of code, by making the sorting order explicit.
This feature should not result in any performance problems - after all, the sorting function simply have to reverse the boolean result when comparing values.
This feature request was taken up in #14989 - there's a lot of good discussion there on this topic.
I just wanted to chime in here that you can already get reversed sorting without any copies with ndarray.sort and indexing:
>>>a=np.arange(1e6, dtype=int)
>>>rg=np.random.default_rng()
>>>rg.shuffle(a)
>>>a.sort() # In-place, ascending order>>>a=a[::-1] # A view, no copies made
Interestingly, the here "descending" is used. I am a bit uncertain about that choice, since it is at odds with Pythons sorted and sort.
In general, we should probably solve this in C, this may require adding more sorting "methods" in C, which was not possible for a long time.
However, NEP 41+43 now makes it possible in a pretty straight-forward manner. I could help with that first step (extending the machinery, or at least providing a blueprint for it), but I don't think I can commit time to the feature itself. If anyone can make it a their larger project, please let me know so I can help with that first step.
(It is pretty new API, so there is no direct blueprint, me making a start on it would probably safe a lot of time for anyone diving into it.)
Adding one more note, since it is easy to miss. Not only is just reverting not stable, there is also the problem of NaN sort order.
To me it seems best if NaNs are always sorted to the end if such an option is added, in other words it preserves -reverse)sort(-x) == sorted(x) (doesn't work for integers mostly because the - doesn't behave right).
Strongly upvote and here is why.
Recently I needed a descending sort function, generic over dimension (3 dimensions, sort across any).
StackOverflow suggests 2 main options:
arr[::-1], which is OK, but not applicable to any dimension. I'd need 3 ifs.
-np.sort(-arr), which I choose as an elegant working solution.
It works fine with floats and signed integers. But what is the output for np.uint8? Here it is:
[[[43 40 37 27]
[39 22 46 0]
[42 45 31 47]]
[[41 36 34 20]
[35 11 38 44]
[18 30 23 24]]
[[33 25 29 12]
[ 7 6 15 13]
[17 26 10 14]]
[[32 21 28 5]
[ 1 2 3 4]
[16 19 9 8]]]
See something strange? Vector [0, 44, 13, 4] is not sorted. Whole output is correct except one vector!
This happens due to several factors meeting together:
Code uses - for unsigned type;
numpy doesn't warn about negative unsigned value;
result is almost correct. It is difficult to catch this problem visually, only test helps;
developer has no reverse parameter in np.sort and has to use workrounds.
I bet I'm not alone in making this kind of mistake. How many results out there, which are ... almost correct?
Regarding reverse-sorting along an axis: does np.flip(np.sort(x, axis=axis), axis=axis) do what you want here? Setting aside questions about where NaN values end up in reverse-sorted arrays (which is left unspecified in the array API standard), I think this should give the right result.
Regarding reverse-sorting along an axis: does np.flip(np.sort(x, axis=axis), axis=axis) do what you want here? Setting aside questions about where NaN values end up in reverse-sorted arrays (which is left unspecified in the array API standard), I think this should give the right result.
Yes, it does. I found this discussion and used flip in my code. It works.
It looks like the array API chose descending to match TensorFlow; see here. (I don't mean to try to justify that choice; I just see that was the rationale given.)
Based on #25076 (comment), it looks like this was intended to be addressed in gh-25076, but it didn't make it onto the checklist.
We discussed this at a recent community meeting and the opinions were that Nan sorting is kind of up to us to decide, there is no standard. It is undefined in PyTorch what happens.
We discussed this in a recent triage meeting. The general feeling was that we should have a new sorting function, but we are limited how to add another function into the DType C struct.
As previously pointed out, a simple reversal breaks stability, and negating fails for non-negatable dtypes. This can even lead to subtle bugs, as pointed out by tvladyslav.
Since the most common workarounds are error-prone, I'm strongly in favor of adding a descending argument to sort/argsort. JAX's version of argsort already has it.
In case it's helpful to anyone, here's a workaround that seems to work correctly:
importnumpyasnpdefargsort(a, axis=-1, descending=False):
ifdescending:
a=np.flip(a, axis)
i=np.argsort(a, stable=True)
i=np.flip(i, axis)
i=a.shape[axis] -1-ireturnielse:
returnnp.argsort(a, axis, stable=True)
defimplies(a, b):
return~a|bdefmain():
a=np.array([4, 2, 2, 8, 2, 9, 1], np.uint8)
i=argsort(a, descending=True)
ai=a[i]
print(i)
print(ai)
# The array is sorted in descending order.assert (ai[:-1] >=ai[1:]).all()
# If two elements are equal, the lower-index element appears first.assertimplies(ai[:-1] ==ai[1:], i[:-1] <i[1:]).all()
if__name__=="__main__":
main()
FWIW, #28516 will probably add the basic infrastructure to do this soon.
That said it doesn't implement it and we include other fast sorting code that may not do the right thing out of the box (yet) -- that is, NaNs should be sorted to the end also for reverse by default I think.
Activity
SorteKanin commentedon Oct 16, 2019
Yes, but it should also work for the in-place ndarray.sort() version, like I showed in the code example.
[-]Feature Request: Reverse parameter in np.sort()[/-][+]ENH: Reverse parameter in np.sort()[/+]rossbar commentedon Jul 22, 2020
This feature request was taken up in #14989 - there's a lot of good discussion there on this topic.
I just wanted to chime in here that you can already get reversed sorting without any copies with
ndarray.sortand indexing:eric-wieser commentedon Jul 22, 2020
This approach does not result in a stable sort
seberg commentedon Jun 29, 2022
Interestingly, the here "descending" is used. I am a bit uncertain about that choice, since it is at odds with Pythons
sortedandsort.In general, we should probably solve this in C, this may require adding more sorting "methods" in C, which was not possible for a long time.
However, NEP 41+43 now makes it possible in a pretty straight-forward manner. I could help with that first step (extending the machinery, or at least providing a blueprint for it), but I don't think I can commit time to the feature itself. If anyone can make it a their larger project, please let me know so I can help with that first step.
(It is pretty new API, so there is no direct blueprint, me making a start on it would probably safe a lot of time for anyone diving into it.)
seberg commentedon Jun 27, 2024
Adding one more note, since it is easy to miss. Not only is just reverting not stable, there is also the problem of NaN sort order.
To me it seems best if NaNs are always sorted to the end if such an option is added, in other words it preserves
-reverse)sort(-x) == sorted(x)(doesn't work for integers mostly because the-doesn't behave right).tvladyslav commentedon Oct 31, 2024
Strongly upvote and here is why.
Recently I needed a descending sort function, generic over dimension (3 dimensions, sort across any).
StackOverflow suggests 2 main options:
arr[::-1], which is OK, but not applicable to any dimension. I'd need 3 ifs.-np.sort(-arr), which I choose as an elegant working solution.Now let's try following code:
It works fine with floats and signed integers. But what is the output for
np.uint8? Here it is:[[[43 40 37 27]
[39 22 46 0]
[42 45 31 47]]
[[41 36 34 20]
[35 11 38 44]
[18 30 23 24]]
[[33 25 29 12]
[ 7 6 15 13]
[17 26 10 14]]
[[32 21 28 5]
[ 1 2 3 4]
[16 19 9 8]]]
See something strange? Vector [0, 44, 13, 4] is not sorted. Whole output is correct except one vector!
This happens due to several factors meeting together:
-for unsigned type;np.sortand has to use workrounds.I bet I'm not alone in making this kind of mistake. How many results out there, which are ... almost correct?
jakevdp commentedon Oct 31, 2024
Regarding reverse-sorting along an axis: does
np.flip(np.sort(x, axis=axis), axis=axis)do what you want here? Setting aside questions about whereNaNvalues end up in reverse-sorted arrays (which is left unspecified in the array API standard), I think this should give the right result.tvladyslav commentedon Nov 2, 2024
Yes, it does. I found this discussion and used flip in my code. It works.
[-]ENH: Reverse parameter in np.sort()[/-][+]ENH: `sort`/`argsort`: add `descending` parameter[/+]mdhaber commentedon Dec 1, 2024
It looks like the array API chose
descendingto match TensorFlow; see here. (I don't mean to try to justify that choice; I just see that was the rationale given.)Based on #25076 (comment), it looks like this was intended to be addressed in gh-25076, but it didn't make it onto the checklist.
mattip commentedon Dec 18, 2024
We discussed this at a recent community meeting and the opinions were that Nan sorting is kind of up to us to decide, there is no standard. It is undefined in PyTorch what happens.
mattip commentedon Jan 8, 2025
We discussed this in a recent triage meeting. The general feeling was that we should have a new sorting function, but we are limited how to add another function into the DType C struct.
carlosgmartin commentedon Aug 14, 2025
As previously pointed out, a simple reversal breaks stability, and negating fails for non-negatable dtypes. This can even lead to subtle bugs, as pointed out by tvladyslav.
Since the most common workarounds are error-prone, I'm strongly in favor of adding a
descendingargument tosort/argsort. JAX's version ofargsortalready has it.In case it's helpful to anyone, here's a workaround that seems to work correctly:
seberg commentedon Aug 14, 2025
FWIW, #28516 will probably add the basic infrastructure to do this soon.
That said it doesn't implement it and we include other fast sorting code that may not do the right thing out of the box (yet) -- that is, NaNs should be sorted to the end also for reverse by default I think.
MaanasArora commentedon Jun 30, 2026
I think this was done in #31345, so closing!
Edit: there are some follow-ups in #31423 and #31424, but those are their own issues now :)