www.gusucode.com > mbcmodels 工具箱 matlab 源码程序 > mbcmodels/@mbcboxcox/mbcboxcox.m

    classdef (Hidden) mbcboxcox < mbctransform
    %MBCBOXCOX Box-Cox transformation
    %
    % obj = mbcboxcox(value)
    %    value:  lambda
    %            [lambda,shift,geomean]
    %            {lambda,Y}
    
    %  Copyright 2007-2013 The MathWorks, Inc.
    
    properties
        Lambda= 1;
        Shift = 0;
        Geomean = 1;
        Invert = false;
        DoUpdate = true;
    end
    
    
    properties (Dependent)
        BoxCox
    end
    properties (SetAccess = private,GetAccess = private)
        BoxCoxVersion = 1;
    end
    methods
        
        function obj = mbcboxcox(value)
        %MBCBOXCOX box cox transform constructor
        %
        % obj = mbcboxcox(value)
        
        if nargin
            obj.BoxCox = value;
        else
            obj.Lambda = 1;
        end
        end
        
        function obj = set.Lambda(obj,Value)
        %SET.LAMBDA set function for Lambda property
        
        obj.Lambda = Value;
        if obj.DoUpdate
            obj =  update(obj);
        end
        end
        
        function obj = set.Shift(obj,Value)
        %SET.SHIFT set function for Shift property
        obj.Shift = Value;
        if obj.DoUpdate
            obj =  update(obj);
        end
        end
        
        function obj = set.Geomean(obj,Value)
        %SET.GEOMEAN set function for Geomean property
        obj.Geomean = Value;
        if obj.DoUpdate
            obj =  update(obj);
        end
        end
        
        function  obj = set.DoUpdate(obj,Value)
        %SET.DOUPDATE set function for DoUpdate property
        obj.DoUpdate = Value;
        if obj.DoUpdate
            obj =  update(obj);
        end
        end
        
        function obj = set.BoxCox(obj,value)
        %SET.BOXCOX set function for BoxCox property
        % lam
        % [lam shift]
        % {lam, Y}
        
        if ~iscell(value)
            % value = lambda;
            value={value};
        end
        lam= value{1}(1);
        if length(value{1})>1;
            % shift is second value
            shift=value{1}(2);
        else
            % default is no shift
            shift=0;
        end
        
        if length(value)==2
            % second element is y data;
            y= value{2};
            y(isnan(y))=[];
            
            % calculate shift from to ensure that all y are positive
            my = min(y);
            if my<shift
                shift= abs(my)+1;
            end
            y=y+shift;
            % Calculate the geometric mean of the data
            %  exclude zero from mean calculation
            geo_mean=exp(mean(log(y(y~=0))));
        else
            geo_mean= 1;
        end
        
        obj.DoUpdate = false;
        obj.Lambda = lam;
        obj.Shift = shift;
        obj.Geomean = geo_mean;
        obj.DoUpdate = true;
        end
        
    end
    
    methods (Access=protected)
        function obj = update(obj)
        %UPDATE update transform function
        % define coding transform function
        obj.Fcn = pMakeAnonFcn(obj.Lambda,obj.Shift,obj.Geomean);
        end
        
        function obj = setDerivedFunctions(obj)
        %SETDERIVEDFUNCTIONS form inverse and derivative functions
        
        % form inverse, derivative functions for coding transform
        [obj.Inv,obj.Diff,obj.DiffInv] = pMakeAnonDerived(obj.Lambda,obj.Shift,obj.Geomean);
        end
    end
    
end


function f = pMakeAnonFcn(lam,shift,geo_mean)
%PMAKEANONFCN make anonymous functions for Box Cox Transform

switch lam
    case 0
        % log transform
        % f = @(y) log(y+shift)*geo_mean;
        f = str2func(sprintf('@(y) log(y+ %20.15g)*(%20.15g)',shift,geo_mean));
    case 1
        % no transform
        f = str2func('@(y) y');
    otherwise
        scale   = lam*geo_mean^(lam-1);
        % f= @(y) ((y+shift).^(lam) -1 )/scale;
        f = str2func(sprintf('@(y) ((y+(%20.15g)).^(%20.15g) -1 )/(%20.15g)',shift,lam,scale));
end

end

function [finv,fdiff,fdiffinv] = pMakeAnonDerived(lam,shift,geo_mean)
%PMAKEANONDERIVED make anonymous functions for inverse and derivativs of Box-Cox.

% Not a method - used to form anonymous function for inverse and derivative coding transform
switch lam
    case 0
        % log transform
        % finv = @(y) exp(y/geo_mean) - shift;
        finv = str2func(sprintf('@(y) exp(y/(%20.15g)) - (%20.15g)',geo_mean,shift));
        % fdiff = @(y) geo_mean./(y+shift);
        fdiff = str2func(sprintf('@(y) (%20.15g)./(y+(%20.15g))',geo_mean,shift));
        % fdiff = @(y) exp(y/geo_mean)/geo_mean;
        fdiffinv = str2func(sprintf('@(y) exp(y/(%20.15g))/(%20.15g)',geo_mean,geo_mean));
    case 1
        % no transform
        finv = str2func('@(y) y');
        fdiff = str2func('@(y) 1');
        fdiffinv= str2func('@(y) 1');
    otherwise
        scale   = lam*geo_mean^(lam-1);
        % finv=  @(y) (scale*y+1).^(1/lam)-shift;
        finv= str2func(sprintf('@(y) ((%20.15g)*y+1).^(%20.15g)-(%20.15g)',scale,1/lam,shift));
        % fdiff = @(y) (lam/scale)*(y+shift).^(lam-1);
        fdiff = str2func(sprintf('@(y) (%20.15g)*(y+(%20.15g)).^(%20.15g)',lam/scale,shift,lam-1));
        %fdiffinv = @(y) (scale*y+1).^(1/lam-1)*scale/lam;
        fdiffinv = str2func(sprintf('@(y) (%20.15g)*((%20.15g)*y+1).^(%20.15g)',scale/lam,scale,1/lam-1));
end

end