Replace NaNs with next real value.

3 vues (au cours des 30 derniers jours)
Chad Greene
Chad Greene le 31 Oct 2014
Commenté : Image Analyst le 25 Août 2021
How can I replace all NaN values in an array with the next non-NaN value in the array? I have
x = [NaN 1 1 3 NaN NaN 4];
and I'd like to turn x into
x = [1 1 1 3 4 4 4];
The following works, but I'd like to do it with fewer moving parts:
for k = find(isnan(x))
x(k) = x(find(1:length(x)>k & isfinite(x),1,'first'));
end

Réponse acceptée

Chad Greene
Chad Greene le 1 Nov 2014
Thanks for your suggestions, y'all. It's nice that R2014b has the 'next' and 'previous' options for 1D interpolation. I ended up writing a function to do the job in old 2012b.

Plus de réponses (4)

Image Analyst
Image Analyst le 31 Oct 2014
I wouldn't worry about it. If it works, that way is fine. If you have millions of elements or a 2D image, then there are functions that can do it in the Image Processing Toolbox, like imfill().

Sean de Wolski
Sean de Wolski le 31 Oct 2014
Modifié(e) : Sean de Wolski le 31 Oct 2014
x = [NaN 1 1 3 NaN NaN 4];
idx = isnan(x);
idxnan = find(idx);
idxnotnan = find(~idx);
fillv = interp1([-flintmax idxnotnan],[0 x(idxnotnan)],idxnan,'next');
x(idx) = fillv;
Probably slower and harder to figure out than a for-loop and it requires R2014b; but it's cool!
  2 commentaires
yogan Sganzerla
yogan Sganzerla le 25 Août 2021
Modifié(e) : Image Analyst le 25 Août 2021
Where was the variable flintmax defined?
Image Analyst
Image Analyst le 25 Août 2021
@yogan Sganzerla, flintmax is built-in:
>> flintmax
ans =
9.00719925474099e+15

Connectez-vous pour commenter.


per isakson
per isakson le 31 Oct 2014
Modifié(e) : per isakson le 31 Oct 2014
If &nbsp x(end) &nbsp is a number
while any( isnan( x ) )
x1 = [ x(2:end), inf ];
x( isnan(x) ) = x1( isnan(x) );
end
or
while any( isnan( x ) )
isn = isnan(x);
x( isn ) = x( [false,isn(1:end-1)] );
end
  2 commentaires
yogan Sganzerla
yogan Sganzerla le 12 Juil 2021
Modifié(e) : yogan Sganzerla le 12 Juil 2021
However, if the vector is like the following, it doesn't work properly.
x = [NaN 1 1 3 NaN NaN 4 NaN NaN NaN];
Where the output will be:
[1 1 1 3 4 4 4 NaN NaN NaN]
and my intentions is to be:
[1 1 1 3 4 4 4 4 4 4].
So repeating the last real value until the end (if the vector just has NaN).
What should I add to reach this output?
Thank you for your attention.
Image Analyst
Image Analyst le 12 Juil 2021
@yogan Sganzerla, try this:
x = [NaN 1 1 3 NaN NaN 4 NaN NaN NaN]
nanIndexes = find(isnan(x))
nonNanIndexes = find(~isnan(x))
% Make any leading nans the first non nan value
if nonNanIndexes(1) ~= 1
x(1:nonNanIndexes(1) - 1) = x(nonNanIndexes(1))
end
% Make any trailing nans the last non nan value
if nonNanIndexes(end) ~= length(x)
x(nonNanIndexes(end) + 1 : end) = x(nonNanIndexes(end))
end
% Now regenerate indexes on the changes vector
nanIndexes = find(isnan(x))
nonNanIndexes = find(~isnan(x))
% Replace nan indexes with last non-nan value just prior to it.
for k = 1 : length(nanIndexes)
thisIndex = nanIndexes(k);
x(thisIndex) = x(thisIndex - 1)
end

Connectez-vous pour commenter.


Roger Stafford
Roger Stafford le 31 Oct 2014
Here's another way:
t = isnan(x);
f1 = find(t);
f2 = find(diff([t,false])==-1)+1;
f3 = zeros(1,length(f1));
f3(find(diff([-1,f1])>1)) = diff([0,f2]);
f3 = cumsum(f3);
x2 = [x,x(end)];
x(f1) = x2(f3);

Catégories

En savoir plus sur Logical 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