Search code examples
matlabbsxfun

Sort a matrix with another matrix


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).


Solution

  • 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