How do I gapfill a vector only if gaps (NaNs) are 10 elements or less?

5 次查看(过去 30 天)
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

采纳的回答

Jan
Jan 2021-7-30
编辑:Jan 2021-8-1
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

更多回答(2 个)

KSSV
KSSV 2021-7-30
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')

Walter Roberson
Walter Roberson 2021-7-30
编辑:Walter Roberson 2021-7-30
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)])
bgstarts = 14
bgends = strfind([mask false], [ones(1,N), 0])+N-1
bgends = 24
breakpoints = [1 reshape([bgstarts, bgends+1].',1,[]) length(x)+1]
breakpoints = 1×4
1 14 25 30
pieces = mat2cell(x, 1, diff(breakpoints))
pieces = 1×3 cell array
{[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]}
pieces(1:2:end) = cellfun(@fillgaps, pieces(1:2:end), 'uniform', 0)
pieces = 1×3 cell array
{[1 2 3 5 7 9 10 9 5.6452 4.2029 5 3 2]} {[NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN]} {[12 13 14 15 16]}
cell2mat(pieces)
ans = 1×29
1.0000 2.0000 3.0000 5.0000 7.0000 9.0000 10.0000 9.0000 5.6452 4.2029 5.0000 3.0000 2.0000 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 12.0000 13.0000 14.0000 15.0000 16.0000
  1 个评论
Abigail Morton
Abigail Morton 2021-7-30
Hi Walter,
Thank you for your help! This was how I was thinking of approaching the problem, but I wasn't experienced enough with Matlab to figure out how to do it. I'm going to work through your code and one of the other suggested ones and see which offers the best solution to my problem - thank you for taking the time to help me out!

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Multirate Signal Processing 的更多信息

产品


版本

R2021a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by