Skip to content Skip to sidebar Skip to footer

Undo Or Reverse Argsort(), Python

Given an array 'a' I would like to sort the array by columns sort(a, axis=0) do some stuff to the array and then undo the sort. By that I don't mean re sort but basically reversing

Solution 1:

There are probably better solutions to the problem you are actually trying to solve than this (performing an argsort usually precludes the need to actually sort), but here you go:

>>>import numpy as np>>>a = np.random.randint(0,10,10)>>>aa = np.argsort(a)>>>aaa = np.argsort(aa)>>>a # original
array([6, 4, 4, 6, 2, 5, 4, 0, 7, 4])
>>>a[aa] # sorted
array([0, 2, 4, 4, 4, 4, 5, 6, 6, 7])
>>>a[aa][aaa] # undone
array([6, 4, 4, 6, 2, 5, 4, 0, 7, 4])

Solution 2:

For all those still looking for an answer:

In [135]: r = rand(10)

In [136]: i = argsort(r)

In [137]: r_sorted = r[i]

In [138]: i_rev = zeros(10, dtype=int)

In [139]: i_rev[i] = arange(10)

In [140]: allclose(r, r_sorted[i_rev])

Out[140]: True

Solution 3:

I'm not sure how best to do it in numpy, but, in pure Python, the reasoning would be:

aargsort is holding a permutation of range(len(a)) telling you where the items of aSort came from -- much like, in pure Python:

>>>x = list('ciaobelu')>>>r = range(len(x))>>>r.sort(key=x.__getitem__)>>>r
[2, 4, 0, 5, 1, 6, 3, 7]
>>>

i.e., the first argument of sorted(x) will be x[2], the second one x[4], and so forth.

So given the sorted version, you can reconstruct the original by "putting items back where they came from":

>>> s = sorted(x)
>>> s
['a', 'b', 'c', 'e', 'i', 'l', 'o', 'u']
>>> original = [None] * len(s)
>>> for i, c inzip(r, s): original[i] = c
... >>> original
['c', 'i', 'a', 'o', 'b', 'e', 'l', 'u']
>>> 

Of course there are going to be tighter and faster ways to express this in numpy (which unfortunately I don't know inside-out as much as I know Python itself;-), but I hope this helps by showing the underlying logic of the "putting things back in place" operation you need to perform.

Solution 4:

Super late to the game, but here:

import numpy as np
N = 1000 # or any large integer
x = np.random.randn( N )
I = np.argsort( x )
J = np.argsort( I )
print( np.allclose( x[I[J]] , x ) )
>> True

Basically, argsort the argsort because the nth element of the reverse sort is J[n] = k : I[k] = n. That is, I[J[n]] = n, so J sorts I.

Solution 5:

indices=np.argsort(a) gives you the sorting indices, such that x = a[indices] is the sorted array. y = b[indices] pushs forward the array b to sorted domain. c[indices] = z pulls back z from sorted domain into c in source domain.

For instance,

import numpy as np

n = 3
a = np.random.randint(0,10,n) # [1, 5, 2]
b = np.random.randn(n) # [-.1, .5, .2]
c = np.empty_like(a)

# indices that sort a: x=a[indices], x==np.sort(a) is all True
indices = np.argsort(a) # [0,2,1]# y[i] is the value in b at the index of the i-th smallest value in a
y = b[indices] # [-.1, .2, .5]# say z[i] is some value related to the i-th smallest entry in a 
z = np.random.randn(n) # [-1.1, 1.2, 1.3]
c[indices] = z # inverted the sorting map, c = [-1.1, 1.3, 1.2] 

Post a Comment for "Undo Or Reverse Argsort(), Python"