gusucode.com > datatypes 工具箱matlab源码程序 > datatypes/@timetable/lag.m

    function tt = lag(tt, lagSteps)
%LAG Lag or lead data in a timetable.
%   TT2 = LAG(TT1) shifts the data in each variable in the timetable TT1
%   forward in time (a "lag") by one time step. TT must be regular.
%
%   TT2 = LAG(TT1,DT) shifts the data by the amount of time DT. DT is a duration
%   or calendarDuration, and must be a multiple of TT's regular time step.
%   Positive values of DT shift the data forward in time (a "lag"), negative
%   values shift the data backwards (a "lead").
%
%   LAG(TT,N) shifts the data in the timetable TT1 by N timesteps. Positive
%   values of N shift the data forward in time (a "lag"), negative values shift
%   the data backwards (a "lead").
%
%   Examples:
%
%   % Lag a monthly series of values, and combine with the unlagged values.
%   monthly = timetable(datetime(2016,1:5,3)', [1:5]')
%   lagged = lag(monthly,calmonths(2))
%   combined = synchronize(monthly,lagged)
%
%   % LAG shifts the data and leaves the times alone. An alternative is to
%   % add the lag to the time vector, and leave the data alone.
%   lagged = monthly
%   lagged.Time = lagged.Time + calmonths(2)
%   combined = synchronize(monthly,lagged)
%
%   See also RETIME, SYNCHRONIZE, ISREGULAR.

%   Copyright 2016 The MathWorks, Inc.

import matlab.internal.tableUtils.isScalarInt
import matlab.internal.tableUtils.defaultarrayLike

% Parse inputs
if nargin == 1
    % Timetable must be regular either in absolute time or with respect to a single
    % unit calendarDuration
    if ~isregularTimeDaysMonths(tt)
        error(message('MATLAB:timetable:lag:MustBeRegular'));
    end
    
    % Lag by 1x time interval: get the sign of time difference for correct lead/lag
    % direction with both ascending and descending times.
    lagSteps = sign(seconds(diff(tt.rowDim.labels(1:2))));
    
else % nargin==2
    % LAGSTEPS must be a scalar
    if ~isscalar(lagSteps) 
        error(message('MATLAB:timetable:lag:InvalidLagType'));
    end
    
    if isnumeric(lagSteps)
        % Timetable must be regular in either absolute or calendar time
        if ~isregularTimeDaysMonths(tt)
            error(message('MATLAB:timetable:lag:MustBeRegular'));
        end
        
        % Need the sign of the difference in the times so that lagSteps will be in
        % the right direction for both ascending and descending regular times.
        lagSteps = sign(seconds(diff(tt.rowDim.labels(1:2)))) * lagSteps;
        
    elseif isduration(lagSteps)
        % Timetable must be regular with respective to absolute time
        [tt_isregular, tt_step] = isregular(tt);
        if ~tt_isregular
            error(message('MATLAB:timetable:lag:MustBeRegularInUnits','Time'));
        end
        
        % Transform lagSteps into # multiples of timetable time step
        lagSteps = lagSteps / tt_step;
        
    elseif iscalendarduration(lagSteps)
        % calendarDuration lag is invalid on a duration timetable
        if isduration(tt.rowDim.labels)
            error(message('MATLAB:timetable:lag:calDurLagDurationTimetable'));
        end
        
        % time table interval and lag parts
        calUnits = {'months' 'days' 'time'};
        [nMonthLag, nDayLag, timeLag] = split(lagSteps, calUnits);
        lagParts = [nMonthLag nDayLag seconds(timeLag)];

        % Do not allow calendarDuration lagStep that is not pure
        % multiple of calmonths, caldays or time unit
        if nnz(lagParts)>1
            error(message('MATLAB:timetable:lag:InvalidCaldurationLag'));
        end
        
        % Input timetable MUST be regular WITH RESPECT TO units in specified lag step
        [tt_isregular, tt_step] = isregular(tt, calUnits{lagParts~=0});
        if ~tt_isregular
            error(message('MATLAB:timetable:lag:MustBeRegularInUnits',calUnits{lagParts~=0}));
        end
        
        % Extract the months, days and the time
        if isduration(tt_step)
            ttParts = [0 0 seconds(tt_step)];
        else
            [nMonthStepTT, nDaysStepTT, timeStepTT] = split(tt_step, {'months' 'days' 'time'});
            ttParts = [nMonthStepTT nDaysStepTT seconds(timeStepTT)];
        end
        
        % When a timetable part equals zero, the corresponding lag part must also
        % equal zero; otherwise the lag cannot be multiple of timetable interval
        if any(lagParts(ttParts==0)~=0)
            error(message('MATLAB:timetable:lag:LagMustBeTimeStepMultiple'));
        end
        
        % Compute number of multiples each lag part is of timetable part.
        % Only consider components correspond to non-zero timetable parts,
        % as previous check guarantees the 'zero'-parts already match up.
        lagSteps = lagParts(ttParts~=0)./ttParts(ttParts~=0);
        
        % Lag is whole multiples of timetable interval IF_AND_ONLY_IF each
        % lagParts are equal multiple of corresponding timetable interval
        % parts; in which case lag steps equals to that number of multiple.
        % Otherwise, let 'steps' fall through to error in isScalarInt below
        lagSteps = unique(lagSteps);
        
    else
        error(message('MATLAB:timetable:lag:InvalidLagType'));
    end
    
    % Make sure lagTime is whole multiples of timetable intervals
    if ~isScalarInt(lagSteps)
        error(message('MATLAB:timetable:lag:LagMustBeTimeStepMultiple'));
    end
end

% lagSteps _IS_ whole number multiple of timetable intervals at this point. Cap
% lead/lag steps by number of rows, and perform the lag/lead operation.
lagSteps = sign(lagSteps) * min(abs(lagSteps),tt.rowDim.length); 
tt_data = tt.data;
for iVar = 1:tt.varDim.length
    if lagSteps>=0
        tt_data{iVar}(1+lagSteps:end,:) = tt_data{iVar}(1:end-lagSteps,:);
        tt_data{iVar}(1:lagSteps,:) = defaultarrayLike(size(tt_data{iVar}(1:lagSteps,:)), 'Like', tt_data{iVar});
    else % -ve lag => lead
        tt_data{iVar}(1:end+lagSteps    ,:) = tt_data{iVar}(1-lagSteps:end,:);
        tt_data{iVar}(end+lagSteps+1:end,:) = defaultarrayLike(size(tt_data{iVar}(end+lagSteps+1:end,:)), 'Like', tt_data{iVar});
    end
end
tt.data = tt_data;
end
        
function tf = isregularTimeDaysMonths(tt)    
    tf = isregular(tt,'Time') || isregular(tt,'Days') || isregular(tt,'Months');
end