Add two matrices (element wise addition) together ignoring NaNs

90 visualizaciones (últimos 30 días)
Jeff
Jeff el 25 de Abr. de 2017
Respondida: Tom Dutton el 21 de Feb. de 2020
Hi all,
Can someone help on this? I'm sure it is straight forward but getting stumped. I would simply like to add two matrices together, element-wise, ignoring the NaNs. I realize one solution is to replace NaNs with zeros but I have some reported zeros that I want to be able to later identify. A solution to that is to set any real zeros to extremely small numbers. Rather than doing the above I am wondering if there is any other way to ignoring the NaNs -- I know of sum(...,'omitnan') and nansum() but they work on one matrix or if I concatenate the two matrices together then they aggregate either all rows or all columns depending on the dimension I select.
For example: A = ones(10,3); B = ones(10,3);
% inserting some NaNs and zeros A([1 6 10],1) = NaN; A([3 7],[2 3]) = NaN; B([3 7],2) = 0;
C = A + B;
I would like C = [1 2 2; 2 2 2; 2 0 1; 2 2 2; 2 2 2; 1 2 2; 2 0 1; 2 2 2; 2 2 2; 1 2 2]

Respuesta aceptada

Jeff
Jeff el 25 de Abr. de 2017
Ok, not to waste too much of the MathWorks communities' time but i did find what looks to be the appropriate solution:
tmp = cat(3,A,B); C = nansum(tmp,3);

Más respuestas (2)

KL
KL el 25 de Abr. de 2017
Hi, maybe something like this?
A = ones(10,3);
B = ones(10,3);
A([1 6 10],1) = NaN; A([3 7],[2 3]) = NaN; B([3 7],2) = 0;
C = A + B
C1 = [1 2 2; 2 2 2; 2 0 1; 2 2 2; 2 2 2; 1 2 2; 2 0 1; 2 2 2; 2 2 2; 1 2 2]
a_n = isnan(A);
b_n = isnan(B);
C(a_n) = B(a_n);
C(b_n) = A(b_n);
C

Tom Dutton
Tom Dutton el 21 de Feb. de 2020
First we construct a matrix that has some NaN in:
A = [NaN NaN 1 NaN NaN;
NaN 1 2 1 NaN;
1 2 3 2 1;
NaN 1 2 1 NaN;
NaN NaN 1 NaN NaN];
1. If you want to convert NaN to 0:
A(isnan(A)) = 0;
isnan(A) will identify the elements that are NaN's; " = 0" will turn them into 0 (or any other value!).
2. If you can't do this (as mentioned in the question), you could use an imaginary number to recognise that there used to be a NaN in that position.
A(isnan(A)) = 1j;
All your previous numbers are still there (the real value), whilst your NaN's are now imaginary values of 1 (1j). You can access each with
% Obtain the values of the matrix with NaN changed to 0's:
real(A);
% or
% Obtain the locations of the NaN's, which are now 1's:
imag(A);
Meaning you can now add the matrix real(A) to another matrix, which would ignore the NaN values of A, and then check to see where the NaN's of A were via imag(A).
3. If you can't use imaginary numbers (perhaps you are already using the complex plane in your work), perhaps you could use the previous method of changing NaN's to zeros, but then create another matrix of the same dimentions/size and log where the NaN's were in that?
% Create a matrix with real, imaginary and NaN values in it:
A = [ NaN+j*NaN NaN 1 NaN NaN;
NaN 1+1j 2 1 NaN;
1 2+1j 3+1j 2 1;
NaN 1+1j 2 1+1j NaN;
NaN+j*NaN NaN 1+1j NaN NaN];
% Log where the NaN's are in another matrix:
A_nan = zeros(size(A)); % Makes A_nan the same size as A and all zero's
A_nan(isnan(real(A))) = 1; % Finds the real NaN's
A_nan(isnan(imag(A))) = 1j+A_nan(isnan(imag(A))); % Finds the imaginary NaN's
% Set the imaginary NaN's to zeros in A
A(isnan(imag(A))) = NaN + 0j;
% Set the real NaN's to zeros in A
A(isnan(real(A))) = 0;
It should be noted that for there to be an imaginary NaN, the real value must be NaN as well.
You can't have 1 + NaN*i; it must be NaN + NaN*i.
There is a work around in MATLAB, but it's probably going to be more trouble than it's worth.
There is another page on this here.

Categorías

Más información sobre Logical en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by