vector index of consecutive gap (NaN) lengths?
    1 view (last 30 days)
  
       Show older comments
    
Hi
For a vector A with random, sometime consecutive gaps of NaN, I want to develop a vector B of same length A that will indicate the length of local consecutive gaps for every value in A. B would have zeros for non-NaN locations in A.
so for
A = [2 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
I'd get
B = [0 0 1 0 0 3 3 3 0 2 2 0];
Ideas? Speed is always a virtue.
Thanks!
Tom
2 Comments
Accepted Answer
  Sean de Wolski
      
      
 on 27 Jun 2012
        And if you like Ryan's idea but don't like bwlabel because it's evil:
A = [2 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
CC= bwconncomp(isnan(A));
n = cellfun('prodofsize',CC.PixelIdxList);
b = zeros(size(A));
for ii = 1:CC.NumObjects
  b(CC.PixelIdxList{ii}) = n(ii);
end
3 Comments
  Sean de Wolski
      
      
 on 27 Jun 2012
				BWCONNCOMP makes BWLABEL irrelevant for everything except LABEL2RGB! For that you have LABELMATRIX to convert from the output of BWCONNCOMP.
Anyway, yes, CC.PixelIdxList contains the indices you need to do most matrix manipulations easily and can be fed directly to REGIONPROPS, all while being faster!
More Answers (3)
  Ryan
      
 on 27 Jun 2012
        Thomas' answer is faster, but here is my go:
A = [2 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
idx = isnan(A);
[B n]= bwlabel(idx);
C = B;
prop = regionprops(idx,'Area');
area = cat(1,prop.Area);
for ii = 1:n
    B(C == ii) = area(ii);
end
B
0 Comments
  Andrei Bobrov
      
      
 on 28 Jun 2012
        
      Edited: Andrei Bobrov
      
      
 on 30 Jun 2012
  
      A = [2 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
a = isnan(A);
t1 = find([true, diff(a)~=0]);
N = diff(t1);
out = zeros(size(A));
V = regionprops(a,'PixelIdxList');
out(cat(1,V.PixelIdxList)) = cell2mat(arrayfun(@(x)x*ones(x,1),N(a(t1))','un',0));
OR
A = [2 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
a = isnan(A);
n1 = regionprops(a,'Area');
out = a + 0;
out(a) = cell2mat(arrayfun(@(x)x*ones(1,x),[n1.Area],'un',0));
ADD variant
a = isnan(A);
t = [true,diff(a)~=0];
k = diff(find([t,true]));
k2 = k.*a(t);
out = k2(cumsum(t));
0 Comments
  Thomas
      
 on 27 Jun 2012
        A very crude way.. pretty sure can be done better...
A = [2 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
A(~isnan(A))=0;
A(isnan(A))=1;
c=diff(A);
start=find(c==1)+1;
stop=find(c==-1)+1;
out=stop-start;
for ii=1:length(out)
A(start(ii):(stop(ii)-1))=out(ii);
end
A
5 Comments
  Thomas
      
 on 29 Jun 2012
				another iteration here NaN can be first,last or anywhere in the middle.. 'hopefully'
A = [NaN 4 NaN 7 9 NaN NaN NaN 32 NaN NaN 8];
A(~isnan(A))=0;
A(isnan(A))=1;
c=diff(A);
start=find(c==1)+1;
stop=find(c==-1)+1;
if length(stop)<length(start)
    stop=[stop start(end)+1];
end
if length(start)<length(stop)
    start=[start(1)-1 start];
end
out=stop-start;
for ii=1:length(out)
A(start(ii):(stop(ii)-1))=out(ii);
end
A
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



