Sort a matrix with another matrix

Jacob picture Jacob · Apr 21, 2010 · Viewed 11.1k times · Source

Suppose I have a matrix A and I sort the rows of this matrix. How do I replicate the same ordering on a matrix B (same size of course)?

E.g.

A = rand(3,4);
[val ind] = sort(A,2);
B = rand(3,4);
%// Reorder the elements of B according to the reordering of A

This is the best I've come up with

m = size(A,1);
B = B(bsxfun(@plus,(ind-1)*m,(1:m)'));

Out of curiosity, any alternatives?

Update: Jonas' excellent solution profiled on 2008a (XP):

n = n

0.048524       1.4632       1.4791        1.195       1.0662        1.108       1.0082      0.96335      0.93155      0.90532      0.88976

n = 2m

0.63202       1.3029       1.1112       1.0501      0.94703      0.92847      0.90411       0.8849       0.8667      0.92098      0.85569

It just goes to show that loops aren't anathema to MATLAB programmers anymore thanks to JITA (perhaps).

Answer

Jonas picture Jonas · Apr 21, 2010

A somewhat clearer way to do this is to use a loop

A = rand(3,4);
B = rand(3,4);
[sortedA,ind] = sort(A,2);

for r = 1:size(A,1)
   B(r,:) = B(r,ind(r,:));
end

Interestingly, the loop version is faster for small (<12 rows) and large (>~700 rows) square arrays (r2010a, OS X). The more columns there are relative to rows, the better the loop performs.

Here's the code I quickly hacked up for testing:

siz = 10:100:1010;
tt = zeros(100,2,length(siz));

for s = siz
    for k = 1:100

        A = rand(s,1*s);
        B = rand(s,1*s);
        [sortedA,ind] = sort(A,2);

        tic;
        for r = 1:size(A,1)
            B(r,:) = B(r,ind(r,:));
        end,tt(k,1,s==siz) = toc;

        tic;
        m = size(A,1);
        B = B(bsxfun(@plus,(ind-1)*m,(1:m).'));
        tt(k,2,s==siz) = toc;

    end
end

m = squeeze(mean(tt,1));

m(1,:)./m(2,:)

For square arrays

ans =

    0.7149    2.1508    1.2203    1.4684    1.2339    1.1855    1.0212    1.0201    0.8770       0.8584    0.8405

For twice as many columns as there are rows (same number of rows)

ans =

    0.8431    1.2874    1.3550    1.1311    0.9979    0.9921    0.8263    0.7697    0.6856    0.7004    0.7314