2011-08-11 76 views
6

我有一個已排序的bigmatrix。但是,我需要按照另一個矩陣中的ID順序重新排序(col. 1 here for both matrices)。我怎樣才能做到這一點使用矢量化?例如:根據第二個矩陣中給出的順序對矩陣進行排序(MATLAB)

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 ; ] ; 

這可能是所有的一些的ID(此處整數)在ordermat可能不會出現在bigmat。如上所示,可以忽略它們,其編號爲id = 6。謝謝!

+0

你是什麼意思通過矢量化? – Mark

+0

我的意思是沒有在bigmatrix上使用for-loop。我希望解決方案使用「ismember」等功能。Bigmatrix擁有超過50萬行。 – Maddy

回答

1
%# 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's 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, :); 
2

這裏是我的解決方案:

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,:); 

我確信它可以處理不同的情況,如:

  • ordermat包含bigmat未發現標識:不是bigmat所有ID都代表ordermat = [2;1;4;3;6]
  • ordermat中:ordermat = [2;1]
  • ID不連續和/或無法啓動在1:ordermat=ordermat+10; bigmat=bigmat+10;
+0

'grp2idx'是否需要統計工具箱? – nibot

+0

@nibot:是的,但它是一個非常流行的工具箱,我認爲每個人都有它:) – Amro

+0

我們可以使用UNIQUE函數的第三個參數代替GRP2IDX – Amro

0

我會根據唯一標識符拆分bigmat成塊,然後重新排列塊,像這樣:

%# this assumes bigmat is sorted, btw 
%# i.e. 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}); 
+1

另一種方法是對數字ordermat,使用intlut來替換每個索引值與它的數字,然後使用sortrows,然後是反向intlut。希望這是明確的 - 我不知道足夠的matlab發佈完整的答案,所以添加爲評論。 –