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

1 次查看(过去 30 天)
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 个评论
Image Analyst
Image Analyst 2019-3-26
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 2019-3-26
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.

请先登录,再进行评论。

采纳的回答

madhan ravi
madhan ravi 2019-3-26
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.

更多回答(1 个)

Guillaume
Guillaume 2019-3-26
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)) = []

类别

Help CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

产品


版本

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by