How to interpolate at NaN values?

204 vues (au cours des 30 derniers jours)
Mr M.
Mr M. le 30 Juin 2018
Modifié(e) : Stephen23 le 8 Déc 2020
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 commentaires
jonas
jonas le 30 Juin 2018
Yes, see previous question here ( link )
Paolo
Paolo le 30 Juin 2018
Is it really interpolation? Whenever you have three consecutive NaN they all have the same value.

Connectez-vous pour commenter.

Réponse acceptée

Stephen23
Stephen23 le 30 Juin 2018
Modifié(e) : Stephen23 le 30 Juin 2018
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 commentaires
Fernand ASSENE
Fernand ASSENE le 7 Déc 2020
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 le 7 Déc 2020
Modifié(e) : Stephen23 le 8 Déc 2020
@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...

Connectez-vous pour commenter.

Plus de réponses (2)

Jan
Jan le 30 Juin 2018
Modifié(e) : Jan le 30 Juin 2018
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 le 4 Sep 2019
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]

Catégories

En savoir plus sur Interpolation of 2-D Selections in 3-D Grids dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by