How to filter a matrix Row by Row to get the highest value?

1 view (last 30 days)
Dear all,
I have this matrix
A= [ 31,62.3, 31,96.3, 31,52.8, 57,91.4 ;...
71,64.4, 31,93.5, 31,36.2, 57,83.1 ] ;
I want to scan this matrix row by row such that values at the odd columns will not be repeated + it will get the highest value at the even column attached to it
So I want the following answer:
Answer = [ 31,96.3 57,91.4 0,0 ;...
71,64.4 31,93.5 57,83.1 ]
The oreder of pairs in each row is not important. The following answe is also OK
Answer = [ 57,91.4 31,96.3 0,0 ;...
31,93.5 57,83.1 71,64.4 ]
Many thanks in advance.
  4 Comments
Image Analyst
Image Analyst on 26 Mar 2019
It's such a quirky thing to do that you may have to end up just writing a custom program from low level functions like for loops and max(). I don't think there is a built in function to do exactly this thing. But there are a lot of ways it could be done from low level functions.
Why do you need to do this unusual thing anyway - what's the use case?
By the way, "raw" means "uncooked food", and a line of an array is "row", not "raw".
Ghost
Ghost on 26 Mar 2019
Thank you Image Analyst. I corrected the spelling.
I just needed this for one idea that I am trying to solve. I don't think it has many applications.

Sign in to comment.

Accepted Answer

madhan ravi
madhan ravi on 26 Mar 2019
See if this satisfies your needs:
C = zeros(size(A));
for k = 1:size(A,1)
B = reshape(A(k,:),2,[]).';
G = findgroups(B(:,1));
BB = reshape(B(any(B(:,2)==splitapply(@(x)max(x),...
B(:,2),G).',2),:).',1,[]);
C(k,1:numel(BB)) = BB;
end
C(:,all(C==0,1)) = []
Note: Not tested under all circumstances.

More Answers (1)

Guillaume
Guillaume on 26 Mar 2019
A version with no loop, but a few accumarray so may not be faster:
%build demo data
A = [31,62.3, 31,96.3, 31,52.8, 57,91.4 ;...
71,64.4, 31,93.5, 31,36.2, 57,83.1 ];
A = [A; A]; A(4, 5) = 32
%algorithm
workingA = [repelem((1:size(A, 1))', size(A, 2)/2), reshape(A.', 2, []).']; %reshape in 2 columns of pairs and prepend with a column indicating which row the data came from
[urows, ~, id] = unique(workingA(:, [ 1 2]), 'rows'); %identify unique 1st pair element per row
offsets = accumarray(workingA(:, 1), id, [], @max); %need to reset id for each row, so find max id per row
offsets = [0;offsets(1:end-1)];
column = (id - offsets(workingA(:, 1)))*2; %and subtract max of previous row from each row
result = accumarray([urows(id, 1), column], workingA(:, 3), [], @max); %distribute max for each unique pair and row
result = result + [accumarray([urows(id, 1), column-1], workingA(:, 2), [], @(v) v(1)), zeros(size(result, 1), 1)] %add 1st element of each pair
With a loop, a cleaner (in my opinion) version of Madhan's answer:
result = zeros(size(A));
for row = 1:size(A, 1)
[uvals, ~, id] = unique(A(row, 1:2:end));
result(row, 2:2:end) = accumarray(id, A(row, 2:2:end), [size(A, 2)/2, 1], @max);
result(row, 1:2:numel(uvals)*2) = uvals;
end
result(:, all(result == 0, 1)) = []

Categories

Find more on Mathematics in Help Center and File Exchange

Products


Release

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!