How do I gapfill a vector only if gaps (NaNs) are 10 elements or less?
5 views (last 30 days)
Show older comments
I have a time-signal that looks something like this:
x=[1,2,3,5,7,9,10,9, NaN,Nan,5,3,2,Nan,Nan,Nan,Nan,Nan,Nan,Nan,Nan,Nan,Nan,Nan,12,13,14,15,16]
I want to use the fillgaps function to fill the gaps in the data. However, for the sake of having a quality signal at the end, I want to make sure that the function only fills gaps up to 10 numbers long. In my example, I would want it to fill the first two NaNs, but not the last 11. I can't seem to find a function in Matlab that does this, how should I do it?
tl;dr: I need to set a limit on the size of gaps that Matlab fills when using the gapfill (or a similar) function
0 Comments
Accepted Answer
Jan
on 30 Jul 2021
Edited: Jan
on 1 Aug 2021
x = [1,2,3,5,7,9,10,9, NaN,NaN,5,3,2,NaN,NaN,NaN,NaN,NaN, ...
NaN,NaN,NaN,NaN,NaN,NaN,12,13,14,15,16];
y = fillgaps(x);
% Find sequences of NaNs longer than 10:
[B, N] = RunLength(isnan(x));
B(B & N < 10) = false; % Exclude short sequences
Mask = RunLength(B, N); % Inflate again
y(Mask) = nan; % Copy original NaNs to output
ax = axes('NextPlot', 'add');
plot(ax, y);
plot(ax, x, 'o');
function [b, n] = RunLength(x, n)
% Cheap and slower version of:
% https://www.mathworks.com/matlabcentral/fileexchange/41813-runlength
if nargin == 1 % Encode: x -> b, n
d = [true; diff(x(:)) ~= 0]; % TRUE if values change
b = x(d); % Elements without repetitions
n = diff(find([d.', true])); % Number of repetitions
else % Decode: b, n -> x
len = length(n); % Number of bins
d = cumsum(n); % Cummulated run lengths
index = zeros(1, d(len)); % Pre-allocate
index(d(1:len-1)+1) = 1; % Get the indices where the value changes
index(1) = 1; % First element is treated as "changed" also
b = x(cumsum(index)); % Cummulated indices
end
end
More Answers (2)
KSSV
on 30 Jul 2021
You can use interp1. Also have a look on fillmissing.
x=[1,2,3,5,7,9,10,9, NaN,NaN,5,3,2,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,12,13,14,15,16] ;
idx = 1:length(x) ;
x_new = x ;
x_new(isnan(x)) = interp1(idx(~isnan(x)),x(~isnan(x)),idx(isnan(x))) ;
plot(idx,x,'*r',idx,x_new,'b')
2 Comments
Walter Roberson
on 30 Jul 2021
Edited: Walter Roberson
on 30 Jul 2021
format short
N = 10;
x = [1,2,3,5,7,9,10,9, NaN,NaN,5,3,2,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,12,13,14,15,16];
mask = isnan(x);
bgstarts = strfind([false mask], [0 ones(1,N)])
bgends = strfind([mask false], [ones(1,N), 0])+N-1
breakpoints = [1 reshape([bgstarts, bgends+1].',1,[]) length(x)+1]
pieces = mat2cell(x, 1, diff(breakpoints))
pieces(1:2:end) = cellfun(@fillgaps, pieces(1:2:end), 'uniform', 0)
cell2mat(pieces)
See Also
Categories
Find more on Multirate Signal Processing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!