dylan2106
dylan2106

Reputation: 402

speed up replace NaNs with last non-Nan value

I'd like to replace all the NaNs in a vector with the last previous non-NaN value

input =  [1 2 3 NaN NaN 2];
output = [1 2 3 3   3   2];

i'd like to try and speed up the loop I already have

input = [1 2 3 NaN NaN 2];

if isnan(input(1))
    input(1) = 0;
end

for i= 2:numel(input)
    if isnan(input(i))
        input(i) = input(i-1);
    end
end

thanks in advance

Upvotes: 4

Views: 2271

Answers (4)

Vegg
Vegg

Reputation: 1

nan_ind = find(isnan(A)==1);
A(nan_ind) = A(nan_ind-1);

Upvotes: -1

Dennis Jaheruddin
Dennis Jaheruddin

Reputation: 21563

Not fully vectorized but quite simple and probably still fairly efficient:

x = [1 2 3 NaN NaN 2];
for f = find(isnan(x))
    x(f)=x(f-1);
end

Of course this is only slightly different than the solution provided by @Hugh Nolan

Upvotes: 0

David K
David K

Reputation: 1346

Since you want the previous non-NaN value, I'll assume that the first value must be a number.

while(any(isnan(input)))
    input(isnan(input)) = input(find(isnan(input))-1);
end

I profiled dylan's solution, Oleg's solution, and mine on a 47.7 million long vector. The times were 12.3s for dylan, 3.7 for Oleg, and 1.9 for mine.

Upvotes: 2

Oleg
Oleg

Reputation: 10676

Here a commented solution, works for a vector only but might be enxtended to work on a matrix:

A = [NaN NaN 1 2 3 NaN NaN 2 NaN NaN NaN 3 NaN 5 NaN NaN];

% start/end positions of NaN sequences
sten = diff([0 isnan(A) 0]);
B    = [NaN A];
% replace with previous non NaN
B(sten == -1) = B(sten == 1);
% Trim first value (previously padded)
B = B(2:end);

Comparison

A: NaN NaN 1 2 3 NaN NaN 2 NaN NaN NaN 3 NaN 5 NaN NaN
B: NaN NaN 1 2 3 NaN   3 2 NaN NaN   2 3   3 5 NaN   5

Upvotes: 0

Related Questions