Reputation: 3744
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
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
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
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
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