How to interpolate at NaN values?
조회 수: 166 (최근 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
Paolo
2018년 6월 30일
Is it really interpolation? Whenever you have three consecutive NaN they all have the same value.
채택된 답변
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
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
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.:
- the first non-NaN value
- a value extrapolated from the first two or more non-NaN values.
- 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
- 0
- something else...
추가 답변 (3개)
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.
댓글 수: 0
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]
댓글 수: 0
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)
댓글 수: 0
참고 항목
카테고리
Help Center 및 File 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!