Find maximum array values avoiding mat2cell.

1 vue (au cours des 30 derniers jours)
Santos García Rosado
Santos García Rosado le 28 Déc 2020
Hello Matlab community.
I was wondering if someone could give me a hand with a code problem I've been having for a while.
So I have an array A =1xn such as:
(NaN, NaN, NaN, NaN, 1, 6, 8, 32, -5, NaN,NaN,NaN,NaN,NaN,NaN, 65, 2 ,16 80, 35, 26, 12, NaN, ..., n).
As you can tell, both the NaN and numeric lenghts do not follow any pattern. The main idea is trying to get the maximum value of each numeric string and being able to get this sort of array as an output:
(NaN, NaN, NaN, NaN, 0, 0, 0, 32, 0, NaN,NaN,NaN,NaN,NaN,NaN, 0, 0 ,0 80, 0, 0, 0, NaN, ..., n).
I'd like to do it without using the mat2cell function since later on I'll have to use the code for Simulink and this kind of function is not allowed by the software.
My first idea was using the common max function:
[value, position] = max(A);
Obviously this will only give me the maximum number of the whole array.
It would be great if someone could help me out. Thank's in advanced!
  2 commentaires
Rik
Rik le 28 Déc 2020
Can't you just call any function with a function block? I haven't worked with Simulink in a very long time, so I don't know which function would or wouldn't be allowed.
Santos García Rosado
Santos García Rosado le 4 Jan 2021
No. There are a couple of matlab functions that simulink's function block doesn't support.

Connectez-vous pour commenter.

Réponse acceptée

Bruno Luong
Bruno Luong le 28 Déc 2020
Modifié(e) : Bruno Luong le 28 Déc 2020
Just a for-loop (is it allowed in Simulink?)
A=[NaN, NaN, NaN, NaN, 1, 6, 8, 32, -5, NaN,NaN,NaN,NaN,NaN,NaN, 65, 2 ,16 80, 80, 35, 26, 12, NaN];
imax = [];
Amax = -Inf;
for i=1:length(A)
if isnan(A(i))
imax = [];
Amax = -Inf;
else
if A(i) > Amax
A(imax) = 0;
imax = i;
Amax = A(imax);
else
A(i) = 0;
end
end
end
  5 commentaires
Santos García Rosado
Santos García Rosado le 30 Déc 2020
Ok, thanks anyways!
Jan
Jan le 30 Déc 2020
See my answer to solve this different problem.

Connectez-vous pour commenter.

Plus de réponses (3)

Jan
Jan le 30 Déc 2020
Modifié(e) : Jan le 30 Déc 2020
For the expanded question in the comment to Bruno's solution you ask for the n largest elements:
A = [NaN, NaN, NaN, NaN, 1, 6, 8, 32, -5, NaN,NaN,NaN,NaN,NaN,NaN, 65, 2 ,16 80, 35, 26, 12, NaN]
n = 3;
BlockMaxK(A, n)
% NaN, NaN, NaN, NaN, 0, 6, 8, 32, 0, NaN, NaN, NaN, NaN, NaN, NaN, 65, 0, 0, 80, 35, 0, 0, NaN
function B = BlockMaxK(A, n)
m = [true, isnan(A), true];
ini = strfind(m, [true, false]);
fin = strfind(m, [false, true]) - 1;
B = nan(size(A));
for k = 1:numel(ini)
ik = ini(k);
fk = fin(k);
[v, ind] = maxk(A(ik:fk), n);
B(ik:fk) = 0;
B(ik - 1 + ind) = v;
end
end
  1 commentaire
Santos García Rosado
Santos García Rosado le 4 Jan 2021
Thank's Jan! This works great, now the code is much more efficient.

Connectez-vous pour commenter.


Bruno Luong
Bruno Luong le 30 Déc 2020
Modifié(e) : Bruno Luong le 30 Déc 2020
This is a method for multiple maxima by block.
I post this for illustration of algorithmic mainly, because the real performance is rather poor, but it should be good theoretically. It uses the so called red-black tree structure, something that MATLAB really miss for decades, and I lost all my fate to see it available one day.
Such method is kind of sequential, meaning it just scan once the data and more adatped for problems where the data are avaiblable sequantially in time (thus simullink framework). Unfortunately the RedBlack library is not as fast as if it was implemented natively in C/C++.
This method can also be seen as an extension of my answer for the original question of single maximum by block.
Here I use a MATLAB implementation by Brain Moore.
A=[NaN, NaN, NaN, NaN, 1, 6, 8, 32, -5, NaN,NaN,NaN,NaN,NaN,NaN, 65, 2 ,16 80, 80, 35, 26, 12, NaN]
k = 3;
% FEX file By Brian Moore
% https://www.mathworks.com/matlabcentral/fileexchange/45123-data-structures
T = RedBlackTree();
for i=1:length(A)
if isnan(A(i))
T.Clear();
else
Insert = T.Count < k;
if ~Insert
Min = T.Minimum();
Insert = A(i) > Min.key;
if Insert
A(Min.value) = 0;
T.Delete(Min);
else
A(i) = 0;
end
end
if Insert
T.Insert(A(i),i);
end
end
end
For a better solution, see Jan's answer.
  1 commentaire
Santos García Rosado
Santos García Rosado le 4 Jan 2021
Thank you Bruno. I'll take a good look at it.

Connectez-vous pour commenter.


Image Analyst
Image Analyst le 28 Déc 2020
Modifié(e) : Image Analyst le 28 Déc 2020
If you have the Image Processing Toolbox you can use regionprops() to ask for the MaxIntensity:
A=[NaN, NaN, NaN, NaN, 1, 6, 8, 32, -5, NaN,NaN,NaN,NaN,NaN,NaN, 65, 2 ,16 80, 80, 35, 26, 12, NaN];
[labeledGroups, numGroups] = bwlabel(~isnan(A))
props = regionprops(labeledGroups, A, 'MaxIntensity');
maxIntensities = [props.MaxIntensity]
output = zeros(size(A));
output(isnan(A)) = nan;
for group = 1 : numGroups
thisGroup = ismember(labeledGroups, group);
% Find out where in this group the max intensity occurs.
indexes = (A .* thisGroup) == maxIntensities(group);
output(indexes) = maxIntensities(group);
end
output % Show in command window.
You'll get
numGroups =
2
maxIntensities =
32 80
output =
Columns 1 through 19
NaN NaN NaN NaN 0 0 0 32 0 NaN NaN NaN NaN NaN NaN 0 0 0 80
Columns 20 through 24
80 0 0 0 NaN
  1 commentaire
Santos García Rosado
Santos García Rosado le 29 Déc 2020
Unfortunately I do not have acces to Image Processing Toolbox at the moment. In case I ever do, I'll try using the code you propose. Thank you anyways.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by