3 votes

Remplacer les valeurs NaN par l'interpolation de leurs valeurs proches dans la matrice

J'ai les données suivantes

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

Je veux remplacer le NaN par la moyenne des valeurs de droite et de gauche. J'essaie de convertir la matrice en vecteur mais l'emplacement du NaN est important, alors je fais ceci

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

Mais les erreurs montrent

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

Le résultat doit être comme ceci

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

1voto

EBH Points 8866

Voici une option sans boucles :

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.'

Résultat :

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

1voto

Sardar Usama Points 13872
[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

1voto

CKT Points 726

Si vous avez R2016a ou une version ultérieure, vous pouvez le faire :

% 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));

Le seul hic ici est qu'il ne préserve pas l'identité de l'utilisateur. NaN dans les endroits où vous n'avez pas deux valeurs à calculer (c'est-à-dire qu'il ne prend pas la moyenne de 19 y NaN à être NaN mais plutôt 19 ). Vous pouvez contourner ce problème en effectuant une étape de post-traitement :

% 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;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X