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

1 回表示 (過去 30 日間)
Ghost
Ghost 2019 年 3 月 25 日
コメント済み: Ghost 2019 年 3 月 27 日
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 件のコメント
Ghost
Ghost 2019 年 3 月 26 日
Thank you very much Madhan.

サインインしてコメントする。

その他の回答 (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 Center および File ExchangeMathematics についてさらに検索

製品


リリース

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by