I have the following problem. I like to replace NaNs with the previous values.
4 5 6 7 8 32 NaN NaN 21 NaN 12 NaN 12 NaN NaN 34 NaN NaN NaN NaN
4 5 6 7 8 32 5 6 21 8 12 5 12 21 8 34 5 12 21 8
I sloved it like this:
for i = 2:5
[r,c] = find(isnan(A(:,i)));
A(r,i) = A(r-1,i);
I'm sure there is a way avoiding the for and the while statement. I search for an "elegant" solution.
Someone's able to help me?
Johannes, notice that your solution will fail if the first value in a column is nan. Rather than looking for a vectorized solution that may end up being rather convoluted (and being slower!), I would simply write a good FOR loop function that can handle all cases. For example, the following solution does not use the FIND function, and only uses simple loops and thus should be very fast:
function A = fill_nans(A) % Replaces the nans in each column with % previous non-nan values.
for ii = 1:size(A,2) I = A(1,ii); for jj = 2:size(A,1) if isnan(A(jj,ii)) A(jj,ii) = I; else I = A(jj,ii); end end end
A = [ 4 5 6 7 8 32 NaN NaN 21 NaN 12 NaN 12 NaN NaN 34 NaN NaN NaN NaN]; indices = isnan(A); A(indices) = 0; B = repmat([4 5 6 7 8],size(A,1),1); A = A+B.*indices;
I do this all the time, my code uses for loops, but I dont see anything wrong with for loops. Im sure there are more elegent solutions but this does the trick for me and is more than fast enough:
function datai = backfillnans(data)
% Dimensions [numRow,numCol] = size(data);
% First, datai is copy of data datai = data;
% For each column for c = 1:numCol % Find first non-NaN row indxFirst = find(~isnan(data(:,c)),1,'first'); % Find all NaN rows indxNaN = find(isnan(data(:,c))); % Find NaN rows beyond first non-NaN indx = indxNaN(indxNaN > indxFirst); % For each of these, copy previous value for r = (indx(:))' datai(r,c) = datai(r-1,c); end end