计算重叠时间间隔的长度

时间:2015-07-01 08:26:14

标签: sas

Location Start      End        Diff
A        01:02:00   01:05:00   3
A        01:03:00   01:08:00   5
A        01:04:00   01:11:00   7
B        02:00:00   02:17:00   17
B        02:10:00   02:20:00   10
B        02:11:00   02:15:00   4

理想输出:

Location OverlapTime(Min) OverlapRecords
A        6                3
B        11               3

如果每次只有同一位置的两个记录重叠,那么我可以通过lag

来完成
data want;
set have;
prevend = lag1(End);
if first.location then prevend = .;
if start < prevend then overlap = 1;else overlap = 0;
overlaptime = -(start-prevend);
by location notsorted;
run;

proc sql;
select location, sum(overlaptime), sum(overlap)
from want
group by location;

但问题是,我在同一位置有很多(未知)重叠时间间隔。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

这是我的解决方案。无需使用lag功能,可以使用retain语句以及firstlast完成此操作。

/* create dummy dataset */
data have;
input Location $ Start :time.  End :time.;
format start end time.;
datalines;
A        01:02:00   01:05:00
A        01:03:00   01:08:00
A        01:04:00   01:11:00
A        01:13:00   01:15:00
B        02:00:00   02:17:00
B        02:10:00   02:20:00
B        02:11:00   02:15:00
C        01:25:00   01:30:00
D        01:45:00   01:50:00
D        01:51:00   01:55:00
;
run;

/* sort data if necessary */
proc sort data = have;
by location start;
run;

/* calculate overlap */
data want;
set have;
by location start; 
retain _stime _etime _gap overlaprecords; /* retain temporary variables from previous row */
if first.location then do; /* reset temporary and new variables at each change in location */
    _stime = start;
    _etime = end;
    _gap = 0;
    _cumul_diff = 0;
    overlaprecords=0;
    end;
_cumul_diff + (end-start); /* calculate cumulative difference between start and end */
if start>_etime then _gap + (start-_etime); /* calculate gap between start time and previous highest end time */
if not first.location and start<_etime then do; /* count number of overlap records */
            if overlaprecords=0 then overlaprecords+2; /* first overlap record gets count of 2 to account for previous record */
            else overlaprecords + 1; 
            end;
if end>_etime then _etime=end; /* update _etime if end is greater than current value */
if last.location then do; /* calculate overlap time when last record for current location is read */
    overlaptime = intck('minute',(_etime-_stime-_gap),_cumul_diff);
    output;
    end;
drop _: start end; /* drop unanted variables */
run;