find length NaN segments
Afficher commentaires plus anciens
I have large vectors, containing quite a lot of NaN samples. I want to know the length of each array of NaNs within this vector, even when this equals 1. So I want to have the lenght of all NaN segments.
Thanks in advance!
1 commentaire
Stephen23
le 22 Fév 2019
Note to future readers: the accepted answer fails for many simple cases:
Only NaN
>> A = [NaN,NaN,NaN,NaN];
>> index=find(isnan(A));
>> idx=find(diff(index)~=1);
>> R=[idx(1) diff(idx) numel(index)-idx(end)]
Attempted to access idx(1); index out of bounds because numel(idx)=0.
Only Numbers
>> A = [1,2,3,4];
>> index=find(isnan(A));
>> idx=find(diff(index)~=1);
>> R=[idx(1) diff(idx) numel(index)-idx(end)]
Attempted to access idx(1); index out of bounds because numel(idx)=0.
Empty Vector
>> A = [];
>> index=find(isnan(A));
>> idx=find(diff(index)~=1);
>> R=[idx(1) diff(idx) numel(index)-idx(end)]
Attempted to access idx(1); index out of bounds because numel(idx)=0.
Leading Numbers
>> A = [1,NaN,NaN,NaN];
>> index=find(isnan(A));
>> idx=find(diff(index)~=1);
>> R=[idx(1) diff(idx) numel(index)-idx(end)]
Attempted to access idx(1); index out of bounds because numel(idx)=0.
Trailing Numbers
>> A = [NaN,NaN,NaN,1];
>> index=find(isnan(A));
>> idx=find(diff(index)~=1);
>> R=[idx(1) diff(idx) numel(index)-idx(end)]
Attempted to access idx(1); index out of bounds because numel(idx)=0.
Réponse acceptée
Plus de réponses (3)
This is simpler and actually works for all horizontal vectors (unlike the accepted answer):
>> A = [NaN NaN NaN 1 2 3 4 NaN 3 44 NaN];
>> D = diff([false,isnan(A),false]);
>> find(D<0)-find(D>0)
ans =
3 1 1
For a slightly faster version you can call find once:
>> F = find(diff([false,isnan(A),false]));
>> F(2:2:end)-F(1:2:end)
ans =
3 1 1
EDIT: uses Jan's logical vector suggestion.
8 commentaires
madhan ravi
le 21 Fév 2019
Modifié(e) : madhan ravi
le 21 Fév 2019
Even the accepted answer works as mentioned exactly in the comment.
madhan ravi
le 21 Fév 2019
I accept it's simpler than the accepted answer but I don't think it's faster:
>> A = [NaN NaN NaN 1 2 3 4 NaN 3 44 NaN];
tic
for k=1:1e5
D = diff([0,isnan(A),0]);
find(D<0)-find(D>0);
end
toc
tic
for k=1:1e5
index=find(isnan(A));
idx=find(diff(index)~=1);
R=[idx(1) diff(idx) numel(index)-idx(end)];
end
toc
Elapsed time is 1.533159 seconds.
Elapsed time is 0.308740 seconds.
>>
Jos (10584)
le 21 Fév 2019
A diff-find-diff solution :-D
D = diff(find(diff([0,isnan(A),0])))
R = D(1:2:end)
Stephen23
le 22 Fév 2019
"Even the accepted answer works as mentioned exactly in the comment."
Except when it doesn't work:
madhan ravi
le 22 Fév 2019
Stephen23
le 22 Fév 2019
Faster, although not as fast as Jan's STRFIND solution:
madhan ravi
le 22 Fév 2019
Yes but in this thread :D.
Stephen23
le 22 Fév 2019
"Yes but in this thread "
The main difference is swapping == for isnan (which everyone used). I doubt that it makes much difference, but you are welcome to do some tests and post the results here.
[B, N] = RunLength(A);
Result = N(isnan(B));
Or:
y = [false, isnan(A), false];
Result = strfind(y, [true, false]) - strfind(y, [false,true])
For this test vector:
A = ones(1, 1e5);
A(randperm(1e5, 5e4)) = NaN;
D = diff(find(diff([false, isnan(A), false])));
R = D(1:2:end);
KSSV
le 21 Fév 2019
0 votes
Read about isnan and nnz
4 commentaires
madhan ravi
le 21 Fév 2019
nnz will give you the total number of elements not the length of each array of nans
KSSV
le 21 Fév 2019
A = [NaN NaN NaN 1 2 3 4 NaN] ;
nnz(isnan(A))
There are four NaN's.
madhan ravi
le 21 Fév 2019
Modifié(e) : madhan ravi
le 21 Fév 2019
OP wants it like 3 nans and 1 nan not the total number of nans or the length of each numbers inbetween nans.
KSSV
le 21 Fév 2019
he can use diff anddo that..
Catégories
En savoir plus sur Logical dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!