matlab: sum values of different sized subarrays without loop

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

Answers (2)

Divakar
Divakar

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

Shai
Shai

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

Related Questions