gusucode.com > bigdata 工具箱 matlab源码程序 > bigdata/@tall/var.m

    function varX = var(varargin)
%VAR Variance
%   Supported syntaxes:
%   Y = VAR(X)
%   Y = VAR(X,FLAG) where FLAG is 0 or 1
%   Y = VAR(X,FLAG,DIM)
%   Y = VAR(...,MISSING)

%   Copyright 2015-2016 The MathWorks, Inc.

narginchk(1, 4);
checkNotTall(upper(mfilename), 1, varargin(2:end));
[args, flags] = splitArgsAndFlags(varargin{:});
if numel(args) == 1
    % No flag provided, let's provide one
    args{2} = 0;
end

dimCell = cell(1, numel(args) - 2);
[x, normFlag, dimCell{:}] = deal(args{:});
% First argument must be numeric or logical for VAR
x = tall.validateType(x, mfilename, {'numeric', 'logical'}, 1);

if ~(isnumeric(normFlag) && ~isobject(normFlag) && isscalar(normFlag))
    error(message('MATLAB:bigdata:array:WeightVectorNotSupported', 'VAR'));
end

if normFlag ~= 0 && normFlag ~= 1
    error(message('MATLAB:bigdata:array:VarFlagZeroOrOne'));
end

adaptor = x.Adaptor;
missingFlagCell = adaptor.interpretReductionFlags(upper(mfilename), flags);
assert(~isempty(missingFlagCell));
missing = missingFlagCell{1};


% If no dimension specified, try to deduce it (will stay empty if we can't).
if isempty(dimCell)
    dim = matlab.bigdata.internal.util.deduceReductionDimension(adaptor);
else
    dim = dimCell{1};
end

useDefaultDim = isempty(dim);

if useDefaultDim || isequal(dim, 1)
    % Reduction
    if useDefaultDim
        aggregateFcn = @(chunk, myDim) chunkVar(chunk, normFlag, myDim, missing);
        reduceFcn = @(chunk, myDim) updateVar(chunk, myDim, missing);
        tmpCellPA = reduceInDefaultDim({aggregateFcn, reduceFcn}, x);
        tmpCell = tall(tmpCellPA);
    else
        % DIM is 1
        aggregateFcn = @(chunk) chunkVar(chunk, normFlag, 1, missing);
        reduceFcn = @(chunk) updateVar(chunk, 1, missing);
        tmpCell = aggregatefun(aggregateFcn, reduceFcn, x);
    end

    % output is in the first element of the cell array.
    varX = clientfun(@normalizeOutput, tmpCell, normFlag, size(x), useDefaultDim);
    if ~useDefaultDim
        % set the output size
        varX.Adaptor = computeReducedSize(varX.Adaptor, x.Adaptor, dim, false);
    end
else
    varX = slicefun(@(x) var(x, normFlag, dim, missing), x);
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function outCell = chunkVar(data, flag, dim, missing)
locIsEmpty = isempty(data);

if dim == 1
    locVar = var(data, 1, dim, missing);
    locMean = mean(data, dim, missing);
    
    if locIsEmpty
        % Ensure that a possibly empty chunk does not corrupt the reduction
        % with NaN by setting to zero while preserving the size.
        locVar(:) = 0;
        locMean(:) = 0;
    end
    
    % locVar is scaled by locCount
    if strcmpi(missing, 'includenan')
        locCount = size(data, dim);
    else
        locCount = sum(~isnan(data), dim);
    end
else
    % Conforming size for vertcat
    locVar = var(data, flag, dim, missing);
    locMean = ones(size(data,1),1);    %size(data,1) should be 1 or 0.
    locCount = ones(size(data,1),1);
end
outCell = {locVar, locMean, locCount, locIsEmpty};
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function outCell = updateVar(inCell, dim, missing)
if size(inCell,1) == 1
    outCell = inCell;
else
    assert(dim == 1);
    vVar = cat(1, inCell{:,1});
    vMean = cat(1, inCell{:,2});
    vCount = cat(1, inCell{:,3});
    vIsEmpty = cat(1, inCell{:,4});
    if size(vVar, dim) == 1 || size(vVar, dim) == 0  % return itself
        locVar = vVar;
        locMean = vMean;
        locCount = vCount;
        locIsEmpty = vIsEmpty;
    else
        locCount = sum(vCount,dim);
        if strcmpi(missing,'omitnan')
            vMean(vCount == 0) = 0;
            vVar(vCount == 0) = 0;
        end
        locMean = sum(vCount .* vMean, dim) ./ locCount;
        locVar = sum(vCount .* vVar, dim) ./ locCount + ...
            diff(vMean, 1, dim) .^ 2 .* prod(vCount ./ locCount, dim);
        locIsEmpty = all(vIsEmpty);
    end
    outCell = {locVar, locMean, locCount, locIsEmpty};
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function varX = normalizeOutput(inCell, normFlag, sizeX, dimUnspecified)
varX = inCell{1};
n = inCell{3};
allEmpty = inCell{4};
type = class(varX);

if isequal(sizeX, [0 0]) && dimUnspecified
    % Special case for 0x0 empty input
    % Must expand the output to 1x1 NaN when user did not provide a dim arg
    varX = nan(type);
    return;
end

if allEmpty
    % All chunks were empty so we fill the output with nans of correct type
    % and return early since normFlag does not apply.
    varX(:) = nan(type);
    return;
end

% Bias correct the result
if normFlag == 0
    nm1 = max(n - 1, 1);
    % Bias-correct the result
    varX = varX .* (n./nm1);
end
end