Code covered by the BSD License

# pushNaNs

by

### Daniel (view profile)

Pushes NaNs to the bottom of each column of X.

pushnans( X,truncate )
```function X = pushnans( X,truncate )
% X = PUSHNANS(X,truncate)
%
% Pushes nans to the bottom of each column of X.
% The second input is an optional flag.  If true, the whole-nan rows at the
% bottom of X are removed.
%
% DM, Apr 2013
%

NAN_THRESHOLD_FRACTION = 0.9; %I haven't actually optimised this value, proably system and version dependant

if sum(sum(isnan(X)))/numel(X) > NAN_THRESHOLD_FRACTION %Note we could do a random sample of X rather than all of it, but this is already pretty fast
pickOutNonNansMethod %when there are few non-nans, do this
else
sortAllMethod %when there are loads of non-nans do this
end

function sortAllMethod
[s1,s2] = size(X);

%get a matrix of row indices with indices refering to non-nans at the top of the columns in the original order
[~,row] = sort(isnan(X));

%use the row indicies and manually calcualte the full-index to rearange X
X = X(bsxfun(@plus,uint32((0:s2-1)*s1),uint32(row)));

if exist('truncate','var') && truncate
s2 = max(sum(~isnan(X)));
X(s2+1:end,:) = [];
end
end

function pickOutNonNansMethod
%In this method we use find to get a list of column indices for all the
%non-nan values. We then use "manually" work out the row indicies

one = uint32(1);

%get a list of non-nan vals and their column indices
goodVal = X(~isnan(X));
[~, goodIndCol] = find(~isnan(X));
goodIndCol = uint32(goodIndCol);

%we'll need these dimensions
[s1,s2] = size(X);
s0 = uint32(numel(goodIndCol));

%work out the row indices for each of the non-nan vals in our list

%prepare a new whole-nan matrix of the correct size
if exist('truncate','var') && truncate
s1 = max(goodRowInd);
end
X = nan(s1,s2);

%use our lovely indices to place the non-nans at the top of the rows
X((goodIndCol-one)*uint32(s1) + goodRowInd) = goodVal;
end
end

%}

```