Fill NaN cell with mean of eight surrounding cells in grid data in matlab

3 views (last 30 days)
I am trying to fill the NaN values of grid data with 8 surrounding values but could not understand, what is going wrong here in my matlab code. The data is 752*891*11 %%% (11 years precipitation of 752*891 cells).
for i = 2 : 752
for j = 2 : 891
for k = 1 : 11
if isnan(data(i,j,k)) == 1
data(i,j,k) = nanmean(nanmean(data(i-2:i+2,j-2:j+2,k-2:k+2)));
end
end
end
end
Thanks in advance for help

Accepted Answer

Jan
Jan on 21 Apr 2018
Edited: Jan on 25 Apr 2018

If you want to replace a scalar based on a 3D array, you either need 3 nanmean calls:

nanmean(nanmean(nanmean(data(i-1:i+1, j-1:j+1, k-1:k+1))))

with i-1:i+1, instead of i-2:i+2. This would be easier:

if isnan(data(i,j,k))   % "== 1" is not needed
  tmp         = data(i-1:i+1, j-1:j+1, k-1:k+1);  % 3D block
  data(i,j,k) = nanmean(tmp(:));                  % Make it a vector
end

But this is a 3x3x3 neighborhood with 27 elements, not 8. I assume you mean:

if isnan(data(i,j,k))   % "== 1" is not needed
  tmp1        = data(i-1:i+1, j, k);
  tmp2        = data(i:i, j-1:j+1, k);
  tmp3        = data(i, j, k-1:k+1);
  tmp         = [tmp1(:); tmp2(:); tmp3(:)];  % Create a vector
  data(i,j,k) = nanmean(tmp);
end

Because the center point data(i,j,k) is included 3 times, but ignored by nanmean, you have 6 neighbors now, not 8.

So please explain again, what you exactly want.

  7 Comments
Jan
Jan on 24 Apr 2018
Edited: Jan on 24 Apr 2018

When you access the index i-2:i+2, the loop for i must start at 3, not at 2, because 0 is not a valid index. And the loop must stop at size(data, 1) - 2. Equivalently for j.

Please post a copy of the complete message, if you mention an error in the forum.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 22 Apr 2018
means = conv2(YourMatrix, [1 1 1;1 0 1;1 1 1]/8,'same') ;
mask = isnan(YourMatrix);
YourMatrix(mask) = means(mask);

No loops needed.

Note: you would need a little adjustment to handle a nan on the edge of the matrix, to calculate the means properly.

  4 Comments
Jan
Jan on 22 Apr 2018

A solution to use conv2 with NaNs:

nanX    = isnan(X);
X(nanX) = 0;
mask    = [1 1 1; 1 0 1; 1 1 1];
means   = conv2(X,     mask, 'same') ./ ...
          conv2(~nanX, mask, 'same');
X(nanX) = means(nanX);

But I'm not sure, how this can be applied to the OP's problem. A neighborhood of 6 or 10(?) elements is wanted.

Sign in to comment.

Categories

Find more on Interpolation of 2-D Selections in 3-D Grids in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!