How to interpolate at NaN values?

162 visualizaciones (últimos 30 días)
Mr M.
Mr M. el 30 de Jun. de 2018
Respondida: Laurel Keyes el 30 de Jul. de 2024
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 comentarios
jonas
jonas el 30 de Jun. de 2018
Yes, see previous question here ( link )
Paolo
Paolo el 30 de Jun. de 2018
Is it really interpolation? Whenever you have three consecutive NaN they all have the same value.

Iniciar sesión para comentar.

Respuesta aceptada

Stephen23
Stephen23 el 30 de Jun. de 2018
Editada: Stephen23 el 30 de Jun. de 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 comentarios
Fernand ASSENE
Fernand ASSENE el 7 de Dic. de 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 el 7 de Dic. de 2020
Editada: Stephen23 el 8 de Dic. de 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...

Iniciar sesión para comentar.

Más respuestas (3)

Jan
Jan el 30 de Jun. de 2018
Editada: Jan el 30 de Jun. de 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 el 4 de Sept. de 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]

Laurel Keyes
Laurel Keyes el 30 de Jul. de 2024
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)

Categorías

Más información sobre Interpolation of 2-D Selections in 3-D Grids en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by