Kristada673
Kristada673

Reputation: 3744

How to sort the columns of a matrix in order of some other vector in MATLAB?

Say I have a vector A of item IDs:

A=[50936
   332680
   107430
   167940
   185820
   99732
   198490
   201250
   27626
   69375];

And I have a matrix B whose rows contains values of 8 parameters for each of the items in vector A:

B=[0    0   0   0   0   0   0   0   0   0
   0    0   0   0   0   0   0   0   0   0
   1    0   1   0   0   1   0   1   1   1
   1    0   1   0   0   1   0   1   1   1
   0    0   1   0   0   0   0   1   0   1
   0    0   0   0   0   0   0   1   0   0
   0    0   0   0   0   0   0   0   0   0
   0    0   0   0   0   0   0   0   0   1];

So, column 1 in matrix B represents data of item in row 1 of vector A, column 2 in matrix B represents data of item in row 2 of vector A, and so on. However, I want matrix B to contain the information in a different order of items stored in vector A2:

A2=[185820
    198490
    69375
    167940
    99732
    332680
    27626
    107430
    50936
    201250];

How do I sort them, so that column 1 of matrix B contains data for item in row 1 of vector A2, column 2 of matrix B contains data for item in row 2 of vector A2, and so on?

My extremely crude solution to do this is the following:

A=A'; A2=A2';

for i=1:size(A,2)
    A(2:size(B,1)+1,i)=B(:,i);
end

A2(2:size(B,1)+1,:)=zeros(size(B,1),size(B,2));

for i=size(A2,2)
    for j=size(A,2)
        if A2(1,i)==A(1,j)
            A2(2:end,i)=A(2:end,j);
        end
    end
end

B2 = A2(2:end,:);

But I would like to know a cleaner, more elegant and less time consuming method to do this.

Upvotes: 2

Views: 314

Answers (4)

rahnema1
rahnema1

Reputation: 15837

A possible solution

You can use second output of ismember function.

[~ ,idx] = ismember(A2,A);
B2 = B(:,idx);

Update:I tested both my solution and another proposed by hbaderts

disp('-----ISMEMBER:-------')
tic
    [~,idx]=ismember(A2,A);
toc
disp('-----SORT:-----------')
tic
    [~,idx1] = sort(A);
    [~,idx2] = sort(A2);
    map = zeros(1,size(idx2));
    map(idx2) = idx1;
toc

Here is the result in Octave:

-----ISMEMBER:-------
Elapsed time is 0.00157714 seconds.
-----SORT:-----------
Elapsed time is 4.41074e-05 seconds.

Conclusion: the sort method is more efficient!

Upvotes: 6

Mad Physicist
Mad Physicist

Reputation: 114230

Transpose B so you can concatenate it with A:

C = [A B']

Now you have

C = [ 50936  0  0  1  1  0  0  0  0;
     332680  0  0  0  0  0  0  0  0;
     107430  0  0  1  1  1  0  0  0;
     167940  0  0  0  0  0  0  0  0;
     185820  0  0  0  0  0  0  0  0;
      99732  0  0  1  1  0  0  0  0;
     198490  0  0  0  0  0  0  0  0;
     201250  0  0  1  1  1  1  0  0;
      27626  0  0  1  1  0  0  0  0;
      69375  0  0  1  1  1  0  0  1];

You can now sort the rows of the matrix however you want. For example, to sort by ID in ascending order, use sortrows:

C = sortrows(C)

To just swap rows around, use a permutation of 1:length(A):

C = C(perm, :)

where perm could be something like [4 5 6 3 2 1 8 7 9 10].

This way, your information is all contained in one structure and the data is always correctly matched to the proper ID.

Upvotes: 0

hbaderts
hbaderts

Reputation: 14316

As both A and A2 contain the exact same elements, just sorted differently, we can create a mapping from the A-sorting to the A2-sorting. For that, we run the sort function on both and save indexes (which are the second output).

[~,idx1] = sort(A);
[~,idx2] = sort(A2);

Now, the first element in idx1 corresponds to the first element in idx2, so A(idx1(1)) is the same as A2(idx2(1)) (which is 27626). To create a mapping idx1 -> idx2, we use matrix indexing as follows

map = zeros(size(idx2));
map(idx2) = idx1;

To sort B accordingly, all we need to do is

B2 = B(:, map);

Upvotes: 4

Michael
Michael

Reputation: 1009

[A2, sort_order] = sort(A);
B2 = B(:, sort_order)

MATLAB's sort function returns the order in which the items in A are sorted. You can use this to order the columns in B.

Upvotes: 0

Related Questions