Reputation: 275
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
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 NaN
s 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
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
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