function y = mad(x,flag)
%MAD Mean/median absolute deviation.
% Y = MAD(X) returns the mean absolute deviation of the values in X. For
% vector input, Y is MEAN(ABS(X-MEAN(X)). For a matrix input, Y is a row
% vector containing the mean absolute deviation of each column of X. For
% N-D arrays, MAD operates along the first non-singleton dimension.
%
% MAD(X,1) computes Y based on medians, i.e. MEDIAN(ABS(X-MEDIAN(X)).
% MAD(X,0) is the same as MAD(X), and uses means.
%
% MAD treats NaNs as missing values, and removes them.
%
% See also VAR, STD, IQR.
% References:
% [1] L. Sachs, "Applied Statistics: A Handbook of Techniques",
% Springer-Verlag, 1984, page 253.
% Copyright 1993-2004 The MathWorks, Inc.
% $Revision: 2.10.2.2 $ $Date: 2004/01/24 09:34:28 $
% The output size for [] is a special case, handle it here.
if isequal(x,[])
y = NaN;
return;
end;
if nargin < 2
flag = 0;
end
% Figure out which dimension nanmean will work along.
sz = size(x);
dim = find(sz ~= 1, 1);
if isempty(dim)
dim = 1;
end
% Need to tile the output of nanmean to center X.
tile = ones(1,ndims(x));
tile(dim) = sz(dim);
if flag
% Compute the median of the absolute deviations from the median.
y = nanmedian(abs(x - repmat(nanmedian(x), tile)));
else
% Compute the mean of the absolute deviations from the mean.
y = nanmean(abs(x - repmat(nanmean(x), tile)));
end
function y = nanmedian(x,dim)
%NANMEDIAN Median value, ignoring NaNs.
% M = NANMEDIAN(X) returns the sample median of X, treating NaNs as
% missing values. For vector input, M is the median value of the non-NaN
% elements in X. For matrix input, M is a row vector containing the
% median value of non-NaN elements in each column. For N-D arrays,
% NANMEDIAN operates along the first non-singleton dimension.
%
% NANMEDIAN(X,DIM) takes the median along the dimension DIM of X.
%
% See also MEDIAN, NANMEAN, NANSTD, NANVAR, NANMIN, NANMAX, NANSUM.
% Copyright 1993-2004 The MathWorks, Inc.
% $Revision: 2.12.2.2 $ $Date: 2004/01/24 09:34:33 $
if nargin == 1
y = prctile(x, 50);
else
y = prctile(x, 50,dim);
end
function m = nanmean(x,dim)
%NANMEAN Mean value, ignoring NaNs.
% M = NANMEAN(X) returns the sample mean of X, treating NaNs as missing
% values. For vector input, M is the mean value of the non-NaN elements
% in X. For matrix input, M is a row vector containing the mean value of
% non-NaN elements in each column. For N-D arrays, NANMEAN operates
% along the first non-singleton dimension.
%
% NANMEAN(X,DIM) takes the mean along the dimension DIM of X.
%
% See also MEAN, NANMEDIAN, NANSTD, NANVAR, NANMIN, NANMAX, NANSUM.
% Copyright 1993-2004 The MathWorks, Inc.
% $Revision: 2.13.4.2 $ $Date: 2004/01/24 09:34:32 $
% Find NaNs and set them to zero
nans = isnan(x);
x(nans) = 0;
if nargin == 1 % let sum deal with figuring out which dimension to use
% Count up non-NaNs.
n = sum(~nans);
n(n==0) = NaN; % prevent divideByZero warnings
% Sum up non-NaNs, and divide by the number of non-NaNs.
m = sum(x) ./ n;
else
% Count up non-NaNs.
n = sum(~nans,dim);
n(n==0) = NaN; % prevent divideByZero warnings
% Sum up non-NaNs, and divide by the number of non-NaNs.
m = sum(x,dim) ./ n;
end
function y = prctile(x,p,dim)
%PRCTILE Percentiles of a sample.
% Y = PRCTILE(X,P) returns percentiles of the values in X. P is a scalar
% or a vector of percent values. When X is a vector, Y is the same size
% as P, and Y(i) contains the P(i)-th percentile. When X is a matrix,
% the i-th row of Y contains the P(i)-th percentiles of each column of X.
% For N-D arrays, PRCTILE operates along the first non-singleton
% dimension.
%
% Y = PRCTILE(X,P,DIM) calculates percentiles along dimension DIM. The
% DIM'th dimension of Y has length LENGTH(P).
%
% Percentiles are specified using percentages, from 0 to 100. For an N
% element vector X, PRCTILE computes percentiles as follows:
% 1) The sorted values in X are taken as the 100*(0.5/N), 100*(1.5/N),
% ..., 100*((N-0.5)/N) percentiles.
% 2) Linear interpolation is used to compute percentiles for percent
% values between 100*(0.5/N) and 100*((N-0.5)/N)
% 3) The minimum or maximum values in X are assigned to percentiles
% for percent values outside that range.
%
% PRCTILE treats NaNs as missing values, and removes them.
%
% Examples:
% y = prctile(x,50); % the median of x
% y = prctile(x,[2.5 25 50 75 97.5]); % a useful summary of x
%
% See also IQR, MEDIAN, NANMEDIAN, QUANTILE.
% Copyright 1993-2004 The MathWorks, Inc.
% $Revision: 2.12.4.4 $ $Date: 2004/01/24 09:34:55 $
if ~isvector(p) || numel(p) == 0
error('stats:prctile:BadPercents', ...
'P must be a scalar or a non-empty vector.');
elseif any(p < 0 | p > 100)
error('stats:prctile:BadPercents', ...
'P must take values between 0 and 100');
end
% Figure out which dimension prctile will work along.
sz = size(x);
if nargin < 3
dim = find(sz ~= 1,1);
if isempty(dim)
dim = 1;
end
dimArgGiven = false;
else
% Permute the array so that the requested dimension is the first dim.
nDimsX = ndims(x);
perm = [dim:max(nDimsX,dim) 1:dim-1];
x = permute(x,perm);
% Pad with ones if dim > ndims.
if dim > nDimsX
sz = [sz ones(1,dim-nDimsX)];
end
sz = sz(perm);
dim = 1;
dimArgGiven = true;
end
% If X is empty, return all NaNs.
if isempty(x)
if isequal(x,[]) && ~dimArgGiven
y = nan(size(p),class(x));
else
szout = sz; szout(dim) = numel(p);
y = nan(szout,class(x));
end
else
% Drop X's leading singleton dims, and combine its trailing dims. This
% leaves a matrix, and we can work along columns.
nrows = sz(dim);
ncols = prod(sz) ./ nrows;
x = reshape(x, nrows, ncols);
x = sort(x,1);
nonnans = ~isnan(x);
% If there are no NaNs, do all cols at once.
if all(nonnans(:))
n = sz(dim);
if isequal(p,50) % make the median fast
if rem(n,2) % n is odd
y = x((n+1)/2,:);
else % n is even
y = (x(n/2,:) + x(n/2+1,:))/2;
end
else
q = [0 100*(0.5:(n-0.5))./n 100]';
xx = [x(1,:); x(1:n,:); x(n,:)];
y = zeros(numel(p), ncols, class(x));
y(:,:) = interp1q(q,xx,p(:));
end
% If there are NaNs, work on each column separately.
else
% Get percentiles of the non-NaN values in each column.
y = nan(numel(p), ncols, class(x));
for j = 1:ncols
nj = find(nonnans(:,j),1,'last');
if nj > 0
if isequal(p,50) % make the median fast
if rem(nj,2) % nj is odd
y(:,j) = x((nj+1)/2,j);
else % nj is even
y(:,j) = (x(nj/2,j) + x(nj/2+1,j))/2;
end
else
q = [0 100*(0.5:(nj-0.5))./nj 100]';
xx = [x(1,j); x(1:nj,j); x(nj,j)];
y(:,j) = interp1q(q,xx,p(:));
end
end
end
end
% Reshape Y to conform to X's original shape and size.
szout = sz; szout(dim) = numel(p);
y = reshape(y,szout);
end
% undo the DIM permutation
if dimArgGiven
y = ipermute(y,perm);
end
% If X is a vector, the shape of Y should follow that of P, unless an
% explicit DIM arg was given.
if ~dimArgGiven && isvector(x)
y = reshape(y,size(p));
end