Effacer les filtres
Effacer les filtres

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

1 vue (au cours des 30 derniers jours)
Ghost
Ghost le 25 Mar 2019
Commenté : Ghost le 27 Mar 2019
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 commentaires
Image Analyst
Image Analyst le 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 le 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.

Connectez-vous pour commenter.

Réponse acceptée

madhan ravi
madhan ravi le 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.

Plus de réponses (1)

Guillaume
Guillaume le 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)) = []

Catégories

En savoir plus sur Matrix Indexing dans Help Center et File Exchange

Produits


Version

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by