How to interpolate at NaN values?

조회 수: 166 (최근 30일)
Mr M.
Mr M. 2018년 6월 30일
답변: Laurel Keyes 2024년 7월 30일
I have a vector [1 2 3 NaN 4 4.5 5.5 NaN NaN 6 6 7 NaN NaN NaN 8] and I want [1 2 3 3.5 4 4.5 5.5 5.75 5.75 6 6 7 7.5 7.5 7.5 8]. Is it possible to do this without a for cycle?
  댓글 수: 2
jonas
jonas 2018년 6월 30일
Yes, see previous question here ( link )
Paolo
Paolo 2018년 6월 30일
Is it really interpolation? Whenever you have three consecutive NaN they all have the same value.

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

채택된 답변

Stephen23
Stephen23 2018년 6월 30일
편집: Stephen23 2018년 6월 30일
No loops, no third-party functions, and works for all MATLAB versions:
>> V = [1 2 3 NaN 4 4.5 5.5 NaN NaN 6 6 7 NaN NaN NaN 8];
>> X = ~isnan(V);
>> Y = cumsum(X-diff([1,X])/2);
>> Z = interp1(1:nnz(X),V(X),Y)
Z = 1.00 2.00 3.00 3.50 4.00 4.50 5.50 5.75 5.75 6.00 6.00 7.00 7.50 7.50 7.50 8.00
  댓글 수: 2
Fernand ASSENE
Fernand ASSENE 2020년 12월 7일
Hello Dear Stephen,
First thank for sharing.
I have the problem with your code when matrix begins with nan values, it does not work.
Please do you how can i fix this issue???
Stephen23
Stephen23 2020년 12월 7일
편집: Stephen23 2020년 12월 8일
@Fernand ASSENE: in the original question all NaN were replaced by the average of the two non-NaN values on either side. If you have a NaN at the start then there are no such two values and so you will have to be more specific about what you expect to be returned, e.g.:
  1. the first non-NaN value
  2. a value extrapolated from the first two or more non-NaN values.
  3. something else...
Note that none of these are the same as the original rule, nor is any of them "better" than the others, so I cannot guess which output you want. Consider the example in the original question appended with NaN i.e. [NaN,1,2,3,NaN,4...], what would you expect the first output value to be?:
  1. 1
  2. 0
  3. something else...

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

추가 답변 (3개)

Jan
Jan 2018년 6월 30일
편집: Jan 2018년 6월 30일
a = [1 2 3 NaN 4 4.5 5.5 NaN NaN 6 6 7 NaN NaN NaN 8];
b = 0.5 * (fillmissing(a, 'previous') + fillmissing(a, 'next'))
Or
v = ~isnan(a);
G = griddedInterpolant(find(v), a(v), 'previous');
idx = find(~v);
bp = G(idx);
G.Method = 'next';
bn = G(idx);
b = a;
b(idx) = (bp + bn) / 2;
Some timings:
n = 20;
a = rand(1, 1e6);
a(rand(1, 1e6) < 0.3) = NaN;
tic
for k = 1:n
b = 0.5 * (fillmissing(a, 'previous') + fillmissing(a, 'next'));
end
toc
tic;
for k = 1:n
v = ~isnan(a);
G = griddedInterpolant(find(v), a(v), 'previous');
idx = find(~v);
bp = G(idx);
G.Method = 'next';
bn = G(idx);
b = a;
b(idx) = (bp + bn) / 2;
end
toc
tic;
for k = 1:n
X = ~isnan(a);
Y = cumsum(X-diff([1,X])/2);
b = interp1(1:nnz(X),a(X),Y);
end
toc
R2016b, i7:
Elapsed time is 2.901105 seconds.
Elapsed time is 0.598722 seconds.
Elapsed time is 1.032346 seconds.

Syed Abdul Salam
Syed Abdul Salam 2019년 9월 4일
Why not use smooth function with 2 levels, it will result the same as mentioned in accepted answer.
V = [1 2 3 NaN 4 4.5 5.5 NaN NaN 6 6 7 NaN NaN NaN 8];
Z = smooth(V,2)
Z = [1 2 3 3.500 4 4.500 5.500 5.500 6 6 6 7 7 7.500 8 8]

Laurel Keyes
Laurel Keyes 2024년 7월 30일
There seems to be a matlab function called fillmissing now that assists you in filling in nan entries. See: Fill missing entries - MATLAB fillmissing (mathworks.com)

카테고리

Help CenterFile Exchange에서 Interpolation of 2-D Selections in 3-D Grids에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by