Reputation: 955
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
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
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