I am new to Matlab and I have a matrix:
M =[NaN NaN NaN 2010 5454;
NaN NaN 2009 3000 5000
NaN 2011 3256 5454 6000
2009 4000 5666 6545 5555
5000 5666 6000 7000 8000];
I want to replace values closest to Nan with a value of 2010. I know how to do it manually and one by one. Is there any to create a loop to find these values and replace them? The result should look like this:
M =[NaN NaN NaN 2010 5454;
NaN NaN 2010 3000 5000
NaN 2010 3256 5454 6000
2010 4000 5666 6545 5555
5000 5666 6000 7000 8000];
Thank you in advance.
It is possible without defining any explicit loops. Below are the steps and sample code.
- Use the
find
function to determine which elements are NaN
.
- Then, offset those indices by 1 both in the positive and negative direction to find positions of neighboring elements.
- Finally replace all such locations with required value, after deleting those positions that are outside the array.
Sample code
% Row and column indices of NaN in array `a`
[x, y] = find(isnan(a));
% All 4-neighbor elements around each NaN
r = [x-1 x+1 x x];
c = [y y y-1 y+1];
% Delete those values that are outside the array bounds
% (For NaNs in the edges)
outInd = r < 1 | r > size(a, 1) | c < 1 | c > size(a, 2);
r(outInd) = [];
c(outInd) = [];
% Replace all these neighbors with required value
a(sub2ind(size(a), r, c)) = 2010;
Thanks to @crazyGamer for improving the answer with explanations and clearer variable names.
You can use 2D-convolution to detect entries that are close to a NaN
; select non-NaN
's among those entries, and write the desired value there.
Closeness is defined by means of a neighbourhood binary mask. This usually has 4
neighbours (up, down, left, right) or 8
(including diagonals).
The code is generalized to use either mask as per choice.
Solution
% Data:
M = [ NaN NaN NaN 2010 5454;
NaN NaN 2009 3000 5000;
NaN 2011 3256 5454 6000;
2009 4000 5666 6545 5555;
5000 5666 6000 7000 8000 ];
neighbourhood = [0 1 0; 1 0 1; 0 1 0];
% or [1 1 1; 1 0 1; 1 1 1] for 8-neighbours
new_value = 2010;
% Computations:
nanInds = isnan(M);
nanIndsWithNeighs = conv2(nanInds, neighbourhood, 'same')~=0;
neighInds = ~nanInds & nanIndsWithNeighs; % logical AND
M(neighInds) = new_value;