Ignore NaN when defining a 3-dimensional array

I am using Matlab 2016a; I am trying to split a 3-dimensional array along the third dimension, but where the values ​​are missing. It is very important that the values ​​remain at the same positions in the array, since the position is relative to a geographic location.3-d array

In this image, imagine NaN has random locations, but these Page 1 and 3 have complete data. By spending the third dimension, some vectors will have three data points and some will have two. I need to be able to succumb to the third dimension using all available values. If I were to look at the values ​​for the highlighted Page 1 or Page 3 there shouldn't be any missing values ​​(since there are always 2 or 3 data points), but they will have NaN placeholders where NaN is.

My question is, how can I delineate along the third dimension, ignoring NaN?

I tried using detrend3 (found in Matlab file exchange: https://www.mathworks.com/matlabcentral/fileexchange/61328-detrend3?focused=7203929&tab=function ), which works fine when decrypting 3rd arrays with no missing values.

Depreciation with NaN results in an error. I tried to ignore NaN and also set NaN to -9999 and then ignored that number, but couldn't get this effort to work.

Any guidance on which direction to go would be greatly appreciated.

+3


source to share


1 answer


function detrended = detrendNaN3(A,t)
%DETRENDNAN3 Detrends a matrix with NaNs into the third dimension
%   Input Arguments:
%       - A: NxMxK matrix
%       - t: 1xK time vector

% time to same format as A
t = bsxfun(@times,permute(t,[3 1 2]),ones(size(A)));
% where A == Nan, -> t = NaN
t(isnan(A)) = NaN;
%mean of time each pixel
xm = nanmean(t,3);
% mean of every pixel in A
ym = nanmean(A,3);
% calculate slope using least squares for every pixel
a = nansum(bsxfun(@times,bsxfun(@minus,t,xm),bsxfun(@minus,A,ym)),3)./nansum(bsxfun(@minus,t,xm).^2,3);
% calculate intercept for every pixel
b = ym - a.*xm;
% calculate trend for every pixel
trend = bsxfun(@plus,b,bsxfun(@times,a,t));
% remove trend
detrended = A-trend;
end

      

Even the crude function is fully vectorized, it can be written a little faster - but it is currently very readable and with a matrix of 2500x1700x100 takes about 8 seconds, which I find acceptable.



The updated version is supported when sharing files.

+1


source







All Articles