passerby51
passerby51

Reputation: 955

Averaging over blocks of a vector in MATLAB

Suppose we have a vector v = [NaN NaN 1 2 3 4 NaN NaN NaN 4 5 6] and we would like to find the average of numbers in each contiguous block which is not NaN. What is an efficient way of doing this in MATLAB? (Of course, the actual vector is something much larger than this example.)

Upvotes: 1

Views: 566

Answers (2)

Oleg
Oleg

Reputation: 10676

Here is a vectorized solution that does not require the Image Processing Toolbox.

Suppose your input is slightly more complex (I included a edge case):

v = [NaN NaN 1 2 3 4 NaN NaN NaN 4 5 6 NaN 3 NaN 3 4]

% Index non NaNs
nonNaN      = ~isnan(v(:));

% Find the beginning of a sequence and the element after the end
subs        = diff([0; nonNaN]);
start       = subs == 1;
ends        = subs == -1;
% Start labeling sequences progressively
subs(start) = 1:nnz(start);
subs(ends)  = -(1:nnz(ends));
% Expand the labeling 
subs        = cumsum(subs);

% Use accumarray
accumarray(subs(nonNaN), v(nonNaN),[],@mean)

Upvotes: 4

bla
bla

Reputation: 26069

you can see if this is efficient enough:

b=bwlabel(isfinite(v));
m=zeros(1,max(b));
for n=1:max(b)
   id=find(b==n);
   m(n)=mean(v(id));
end

Surprisingly for long vectors v I found this to be more efficient than the logical indexing option mean(v(b==n))...

Upvotes: 1

Related Questions