AnesG
AnesG

Reputation: 275

Replace NaN values with interpolation of they near values in matrix

I have this data

Mat=[1 2 3 5;6 14 -9999 4;10 11 12 13;14 -9999 16 17;18 19 -9999 -9999]
Mat(Mat<0)=NaN

Mat =
1     2     3     5
6     14   NaN     9
10    11    12    13
14   NaN    16    17
18    19   NaN   NaN

I want to replace the NaN with the mean of the right and left value. I try to convert the all matrix in vector but the location of de NaN is importat so do this

Row = Mat(2,:)
Row = inpaint_nans(Row)

But error show

Undefined function 'inpaint_nans' for input arguments of type 'double'

The result must be like this

Mat =
1     2     3     5
6     14    9     4
10    11    12    13
14    15    16    17
18    19   NaN   NaN

Upvotes: 3

Views: 793

Answers (3)

CKT
CKT

Reputation: 781

If you have R2016a or later you can do:

% Compute moving mean, omitting the NaNs
MatMean = movmean(Mat, 3, 2, 'omitnan');
InterpMat = Mat;
% Set NaN values to the average
InterpMat(isnan(Mat)) = MatMean(isnan(Mat));

The only hiccup here is that it doesn't preserve the NaNs in locations where you don't have 2 values to average (that is, it doesn't take the average of 19 and NaN to be NaN, but rather 19). You can get around this with a post-processing step:

% Find regions where either neighbor of a NaN is NaN
N = size(Mat, 1);
mask = (movsum(isnan(Mat), [1 0], 2) == 2) | (movsum(isnan(Mat), [0 1], 2) == 2);
% Reset those points to NaN
InterpMat(mask) = NaN;

Upvotes: 1

EBH
EBH

Reputation: 10450

Here is an option with no loops:

Mat = [1 2 3 5;6 14 nan 4;10 11 12 13;14 nan 16 17;18 19 nan nan];
% get the transposed location of all NaNs:
loc = reshape(1:numel(Mat),size(Mat.')).'.*isnan(Mat);
% remove first and last column:
nan_loc = nonzeros(loc(:,2:end-1));
% replace them by the mean of the values to thier sides:
tMat = Mat.';
tMat(nan_loc) = mean([tMat(nan_loc-1) tMat(nan_loc+1)],2);
Mat = tMat.'

Result:

Mat =
     1     2     3     5
     6    14     9     4
    10    11    12    13
    14    15    16    17
    18    19   NaN   NaN

Upvotes: 1

Sardar Usama
Sardar Usama

Reputation: 19689

[r,c]=find(isnan(Mat(:,2:end-1)));      % Finding indexes of NaN excluding the edges/corners
c=c+1; % To counter that we started from second column
for iter=1:length(c)
    Mat(r(iter),c(iter))= mean([Mat(r(iter),c(iter)-1)  Mat(r(iter),c(iter)+1)]);
end

Upvotes: 1

Related Questions