MATLAB Answers

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

조회 수: 1(최근 30일)
Abigail Morton
Abigail Morton 2021년 7월 29일
편집: Jan 2021년 8월 1일
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
  댓글 수: 1
Abigail Morton
Abigail Morton 2021년 7월 30일
Thank you so much for your help, this is an elegant solution!

댓글을 달려면 로그인하십시오.

추가 답변(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')
  댓글 수: 2
Abigail Morton
Abigail Morton 2021년 7월 30일
Thanks for the suggestion! As Jan said, I am looking for a code that leaves the long gaps unfilled.

댓글을 달려면 로그인하십시오.


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!

댓글을 달려면 로그인하십시오.

제품


릴리스

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by