1
votes

I have a matrix with several NaN values and I want to replace those with the last non-NaN value. The matrix is very large so ideally I would do it in a vectorized fashion.

Here is a minimal working example:

M = [
NaN NaN NaN 3
7   NaN NaN 1
NaN NaN NaN 9
NaN 6   NaN NaN
NaN NaN NaN NaN
8   NaN NaN 8
NaN 5   NaN NaN
NaN NaN NaN NaN
9   NaN NaN NaN]

And the output should be:

Out = [
NaN NaN NaN 3
7   NaN NaN 1
7   NaN NaN 9
7   6   NaN 9
7   6   NaN 9
8   6   NaN 8
8   5   NaN 8
8   5   NaN 8
9   5   NaN 8]

I was wondering whether anyone faced a similar problem and knows an efficient way to solve it. I have read this similar post but all solutions seem to involve a for loop.

2
Why are you only replacing some NaNs and not others? Is this per column? Per row? Per something else? - excaza
Sorry. It was a typo. I have corrected it. It is per column. - phdstudent
I doubt this is possible, I don't think NAN is probably handled by vectorized functions stackoverflow.com/questions/15560567/… - Antonio
Well the NaNs can be replaced by any arbitrary number such as -99 - phdstudent
I'm still not understanding columns 1 and 2 of your desired output. - excaza

2 Answers

6
votes

Here's one vectorized approach -

mask = ~isnan(M);
cumsums = cumsum(mask,1);
invalid_mask = cumsums==0;
cumsums(invalid_mask) = 1;

shifts = [0 cumsum(sum(mask(:,1:end-1),1))];

idx = bsxfun(@plus,cumsums, shifts);
nums = M(mask);
out = nums(idx);
out(invalid_mask)=nan;
3
votes

Check out the fillmissing function if you have R2016b or beyond. You can use the 'previous' method to do exactly this.