Reputation: 66
I wonder if it is possible to get min/max values of different sized subarrays without using a loop in matlab.
% create a 1D vector with arbitory floating point values
A = rand(100,1,'double');
% get start indexes of sections of A (eg. A>0.9)
pos01 = A>0.9;
posIdx= [1;find(pos01);size(A,1)];
% if 1 or size(A,1) where not required, remove them
posIdx = unique(posIdx);
% min/max all sections:
for ix=1:size(posIdx,1)-1
Amin(ix) = min(A(posIdx(ix):posIdx(ix+1)));
Amax(ix) = max(A(posIdx(ix):posIdx(ix+1)));
end
This last row can be very slow if you have a very large vector A and lots of sections. I wonder how to vectorize this loop in matlab.
I tried to come up with a solution using arrayfun, remap, bsxfun and others. But all the solutions I can think of, require the sections to have equal size - which is not the case :(
Any ideas ?
best, Jens Henrik
Upvotes: 2
Views: 339
Reputation: 221584
bsxfun
approach to replace your for-loop part -
t1 = bsxfun(@le,1:size(A,1),posIdx(2:end)) & bsxfun(@ge,1:size(A,1),posIdx(1:end-1));
t1 = t1';
t2 = A(:,ones(1,size(t1,2))).*t1;
t2(~t1)=nan;
Amin = nanmin(t2);
Amax = nanmax(t2);
Upvotes: 0
Reputation: 114826
Use cumsum
and accumarray
A = rand(100,1,'double');
pos01 = A > 0.9;
subs = ( pos01(1) == 0 ) + cumsum( pos01(:) ); % convert posIdx to subs. note the special treatment of the first entry.
Amin = accumarray( subs, A, [], @min );
Amax = accumarray( subs, A, [], @max );
Upvotes: 2