Sorting sub matrices based on specific column value
Show older comments
Hello All, I try to optimize the following code. I have this example fib_dist_ang matrix. First column numbers are not relevant to discussion. second column values are sorted while third column are not sorted.
I wanted to sort the third column values. This sorting is based on same value in the second column and place the value closest to the theta_ran (e.g. theta_ran =7.0) value. During this sorting based on the third row, In this example, lets confine discussion to last three rows we have to change the all values in the row (like how SORTROWS() command does). Output I requested is as follows:
Notes: 1) I had used UNIQUE to find the first and last rows of the repetitions based on the second column value. 2) To find the closest value, I had used histc.
fib_dist_ang=%required output
2 0.008 5.2
22 0.008 6.2
42 0.014 4.7
43 0.016 7.2
3 0.016 2.2
23 0.016 6.7
fib_dist_ang= %input
22 0.008 6.2
2 0.008 5.2
42 0.014 4.7
23 0.016 6.7
43 0.016 7.2
3 0.016 2.2
%FINDING THE INDICES OF THE REPETATIONS
[~,uniq_first,~] = unique(fib_dist_ang(:,2), 'first');
[~,uniq_last,~] = unique(fib_dist_ang(:,2), 'last');
tic_sortang=tic;
for i2=1:size(uniq_first,1)
%SORTING BASED ON THE THRID COLUMN VALUES IN THE SUB MATRIX
ithrow=sortrows(fib_dist_ang(uniq_first(i2):uniq_last(i2),:),3);
%FINDING CLOSEST VALUE, IF AVAILABLE
val=theta_ran; f=ithrow(:,3);
if val > f(1) && val < f(end) % it can find the closest angle
[N,bin]=histc(val,f);%if val < f(1), then bin=0.
index=bin+1;
if abs(val-f(bin))<abs(val-f(bin+1))
fclosest=f(bin); index=bin;
else
fclosest=f(index);
end
% PLACING THE CLOSEST VALE TO THETA_RAN, IF AVALABLE
ithrow=[ithrow(index,:);ithrow(1:index-1,:);ithrow(index+1:end,:) ];
end
%COPY BACK THE SUB MATRIX INTO THE WHOLE MATRIX.
fib_dist_ang(uniq_first(i2):uniq_last(i2),:)=ithrow;
end
Only this loop is taking almost half of my total program time. Hence, I am looking for any possibility to optimize this program.
4 Comments
Azzi Abdelmalek
on 20 Feb 2016
Edited: Azzi Abdelmalek
on 20 Feb 2016
How did you get this part :
43 0.016 7.2
3 0.016 2.2
23 0.016 6.7
How the third column is sorted?
Azzi Abdelmalek
on 20 Feb 2016
Ok, the closest is value is 7.2, after 7.2 it's 6.7, why in your result, you placed 2.2 in the second position?
Raj Raj
on 20 Feb 2016
Accepted Answer
More Answers (1)
Azzi Abdelmalek
on 20 Feb 2016
a=[22 0.008 6.2
2 0.008 5.2
42 0.014 4.7
23 0.016 6.7
43 0.016 7.2
3 0.016 2.2]
b=a;
b(:,4)=abs(b(:,3)-7)
[ii,jj,kk]=unique(a(:,2))
out=cell2mat(accumarray(kk,(1:numel(kk))',[],@(x) {sortrows(b(x,:),4)}))
out=out(:,1:3)
7 Comments
Raj Raj
on 20 Feb 2016
Azzi Abdelmalek
on 20 Feb 2016
Edited: Azzi Abdelmalek
on 20 Feb 2016
This is the result:
22.0000 0.0080 6.2000
2.0000 0.0080 5.2000
42.0000 0.0140 4.7000
43.0000 0.0160 7.2000
23.0000 0.0160 6.7000
3.0000 0.0160 2.2000
You were asking to sort the third column regarding to the closest value to 7 (6.2 then 5.2)
Guillaume
on 20 Feb 2016
Why isn't the order of the first 2 rows reversed? 6,2 is closer to 7 than 5.2
Azzi Abdelmalek
on 20 Feb 2016
Edited: Azzi Abdelmalek
on 20 Feb 2016
a=[22 0.008 6.2
2 0.008 5.2
42 0.014 4.7
23 0.016 6.7
43 0.016 7.2
3 0.016 2.2]
b=a;
[ii,jj,kk]=unique(a(:,2));
q=accumarray(kk,(1:numel(kk))',[],@(x) {sortrows(a(x,:),3)});
s=cell2mat(q);
[~,idx]=min(abs(s(:,3)-7));
n=cumsum(cellfun(@(x) size(x,1) ,q));
jdx=find(idx<=n,1);
r=sortrows([q{jdx} abs(q{jdx}(:,3)-7)],4);
q{jdx}=r(:,1:3);
out=cell2mat(q)
Raj Raj
on 21 Feb 2016
Categories
Find more on Shifting and Sorting Matrices in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!