Asked by Shakir Hussain
on 21 Apr 2018

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

Answer by Jan
on 21 Apr 2018

Edited by Jan
on 25 Apr 2018

Accepted Answer

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.

Shakir Hussain
on 24 Apr 2018

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.

Shakir Hussain
on 25 Apr 2018

Thank you jan The problem has solved

Sign in to comment.

Answer by 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.

Walter Roberson
on 22 Apr 2018

Ah, good point, the 0 * nan at the point itself makes the conv2() result into nan.

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.

Image Analyst
on 23 Apr 2018

Just change the mask shape and elements to be whatever is wanted.

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.