Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Desort" a vector (undo a sorting)

In Matlab, sort returns both the sorted vector and an index vector showing which vector element has been moved where:

[v, ix] = sort(u);

Here, v is a vector containing all the elements of u, but sorted. ix is a vector showing the original position of each element of v in u. Using Matlab's syntax, u(ix) == v.

My question: How do I obtain u from v and ix?

Of course, I could simply use:

w = zero(size(v));

for i = 1:length(v)
    w(ix(i)) = v(i)
end

if nnz(w == u) == length(u)
    print('Success!');
else
    print('Failed!');
end

But I am having this tip-of-the-tongue feeling that there is a more elegant, single-statement, vectorized way of doing this.


If you are wondering why one would need to do this instead of just using u: I was trying to implement the Benjamini-Hochberg procedure which adjusts each element of the vector based on its position after sorting, but recovering the original order after adjusting was important for me.

like image 831
Superbest Avatar asked Nov 15 '12 22:11

Superbest


1 Answers

The solution is:

w(ix) = v;

This is a valid Matlab operation provided that w is either at least as big as v, or not yet declared.

Example:

>> u = [4 8 10 6 2];
>> [v, ix] = sort(u)

    v = 2 4 6 8 10        
    ix = 5 1 4 2 3

>> u(ix)

    ans = 2 4 6 8 10

>> w(ix) = v

    w = 4 8 10 6 2

(Apologies for the trivial question-answer, but I realized the solution as I was typing the question, and thought it might be useful to someone.)

like image 196
Superbest Avatar answered Sep 30 '22 14:09

Superbest