Sorting a matrix based on the order specified in the second matrix (MATLAB)

I have a large matrix that is sorted. However, I need to reorder it according to the order of identifiers in another matrix ( col. 1 here for both matrices ). How to do this using vectorization? For instance:

 bigmat = [ ... 1 10 ; 1 30 ; 1 40 ; 2 1 ; 2 11 ; 3 58 ; 4 2 ; 4 5 ] ; ordermat = [ 2 ; 1 ; 4 ; 3 ; 6] ; % Integer IDs finalans = [ ... 2 1 ; 2 11 ; 1 10 ; 1 30 ; 1 40 ; 4 2 ; 4 5 ; 3 58 ; ] ; 

It is possible that all some IDs (integers here) in ordermat may not be present in bigmat. They can be ignored, as shown above, using id = 6 . Thanks!

+6
source share
3 answers
 %# Input values: bigmat = [1 10; 1 30; 1 40; 2 1; 2 11; 3 58; 4 2; 4 5]; ordermat = [ 2 ; 1 ; 4 ; 3 ; 6] ; %# Make a look-up table that tells us the relative order for each order id sortmat(ordermat) = 1:length(ordermat); %# Extract the order ID from the big matrix keys = bigmat(:,1); %# Get the new ordering new_key = sortmat(keys); %# Sort the new ordering, remembering the permutation necessary [~, permutation] = sort(new_key); %# Apply the permutation to the big matrix finalans = bigmat(permutation, :); 
+1
source

Here is my solution:

 ordermat = [2; 1; 4; 3; 6]; bigmat = [ 1 10 1 30 1 40 2 1 2 11 3 58 4 2 4 5 ]; %#bigmat = sortrows(bigmat,1); %# keep valid IDs, ord = ordermat( ismember(ordermat,bigmat(:,1)) ); ord = grp2idx(ord); %# starting/ending locations of the different IDs in bigmat startInd = find( diff([0;bigmat(:,1)]) ); endInd = [startInd(2:end)-1; size(bigmat,1)]; %# generate startInd(i):endInd(i) intervals ind = arrayfun(@colon, startInd, endInd, 'UniformOutput',false); %# order then combine the intervals of indices ind = [ind{ord}]; %# get final sorted result finalans = bigmat(ind,:); 

I made sure that it handles different cases, for example:

  • ordermat contains identifiers not found in bigmat : ordermat = [2;1;4;3;6]
  • not all bigmat identifiers bigmat represented in ordermat : ordermat = [2;1]
  • Identifiers are not sequential and / or do not start with 1: ordermat=ordermat+10; bigmat=bigmat+10; ordermat=ordermat+10; bigmat=bigmat+10;
+2
source

I would split bigmat into pieces according to unique identifiers, and then reorder the pieces, for example:

 %# this assumes bigmat is sorted, btw %# ie that the different ids are grouped together %# find unique ids dd = [true;diff(bigmat(:,1))~=0]; uniqueIDs = bigmat(dd,1); %# reorder uniqueIDs [~,newOrder] = ismember(uniqueIDs,ordermat); %# if there are uniqueIDs that are not in ordermat %# we'd need to remove those. I assume this won't %# be the case %# chop up bigmat numUniqueIds = diff([find(dd);length(dd)+1]); bigChunks = mat2cell(bigmat,numUniqueIds,size(bigmat,2)); %# reorder chunks finalans = cat(1,bigChunks{newOrder}); 
0
source

Source: https://habr.com/ru/post/894881/


All Articles