SAS为纵向数据添加新的观察结果

时间:2014-10-08 15:08:52

标签: sas

我在SAS中有一个纵向数据集,其时间段被分类为有事件风险或无风险。不幸的是,一些时间段重叠,我想重新编码它们以获得完全不重叠的观测数据集。例如,数据集目前看起来像:

Row 1: ID=123; Start=Jan 1, 1999; End=Dec 31, 1999; At_risk="Yes"
Row 2: ID=123; Start=Feb 1, 1999; End=Feb 15, 1999; At_risk="No"

我想要的数据集如下:

Row 1: ID=123; Start=Jan  1, 1999; End=Feb  1, 1999; At_risk="Yes"
Row 2: ID=123; Start=Feb  1, 1999; End=Feb 15, 1999; At_risk="No"
Row 3: ID=123; Start=Feb 15, 1999; End=Dec 31, 1999; At_risk="Yes"

思想?

2 个答案:

答案 0 :(得分:0)

此类任务是调试程序逻辑和对抗数据假设的练习,使用旧/新值... 在我提供的确切示例的初始代码下面,肯定需要对实际数据进行一些调整。

如果超过当前下一条记录的时间重叠,我不确定它是否可行(通过合理的努力)。对于这种情况,您可能更有效,将原始起始时间间隔拆分为日级别,然后将细节汇总到新的时间间隔

data orig;
format Id 16. Start End Date9.;
Id = 123;Start='1jan1999'd; End='31dec1999'd; At_risk="Yes";output;
Id = 123;Start='1feb1999'd; End='15feb1999'd; At_risk="No";output;
run;

proc sort data = orig;
by ID Start;
run;

data modified;
    format pStart oStart pEnd oEnd Date9.;
    set orig;
    length pStart pEnd 8 pAt_risk $3;
    by ID descending End ;

    retain pStart pEnd pAt_risk;

    /* keep original values */
    oStart = Start;
    oEnd = End;
    oAt_risk = At_risk;

    if first.id then do;
        pStart = Start;
        pEnd = End;
        pAt_risk = At_risk;
        /* no output */ 
    end;
    else do;
        if pAt_risk ne At_risk then do;
            if Start > pStart then do;
                put _all_;
                Start = pStart;
                End = oStart;
                At_risk = pAt_risk;
                output;/* first part of time span */
                Start = oStart;
                End = oEnd;
                At_risk = oAt_risk;
                output;/* second part of time span */
                if (End < pEnd ) then do;
                    Start = End;
                    End = pEnd;
                    At_risk = pAt_risk;
                    output; /*third part of time span */
                    /* keep current values as previous record values */
                    pStart = max(oStart, Start);
                    pEnd = End;
                    pAt_risk = At_risk;
                end;
            end;
        end;
    end;
run; 

proc print;run;

答案 1 :(得分:0)

Vasja可能会建议这样的事情(日期级别)作为替代。

我将在此假设纵向数据集中读取的最新行优先于具有重叠日期范围的任何其他行。如果不是这种情况,则根据需要调整下面的优先级推导。

您确定开始日期和结束日期是否正确。您所需的输出仍具有重叠日期。 2月1日&amp; 15都是风险而不是风险。您的结束日期应至少在下一个开始日期的前一天。不是同一天。结束日期和开始日期应该是连续的。因此编码产生所需输出(具有重叠日期)的解决方案是有问题的。以下解决方案基于没有重叠的日期。您需要根据所需的输出修改它以包含重叠日期。

/*         Your longitudinal dataset .  */
data orig; 
         format Id 16. Start End Date9.; 
         Id = 123;Start='1jan1999'd; End='31dec1999'd; At_risk="Yes";output; 
         Id = 123;Start='1feb1999'd; End='15feb1999'd; At_risk="No";output; 
run; 

/*         generate a row for each date between start and end dates.  */
/*         Use row number (_n_) to assign priorioty.  */
Data overlapping_dates; 
         set orig; 
         foramt date date9.;
         priority = _n_; 
         do      date = start to end by 1; 
                 output; 
         end; 
Run; 

/*         Get at_risk details for most recent read date according to priority.  */
Proc sql; 
         create  table non_overlapping_dates as 
         select  id, date, at_risk 
         from    overlapping_dates 
         group   by      id, date 
         having  priority eq max (priority) 
         order   by       id, date 
         ; 
Quit; 


/*   Rebuild longitudinal dataset .  */
Data longitudinal_dataset 
    (keep= id start end at_risk)
    ; 
        format id 16. Start End Date9. at_risk $3.;

        set non_overlapping_dates; 
        by id at_risk notsorted; 

        retain start; 

    if  first.at_risk
        then start = date;

/*      output a row to longitudinal dataset if at_risk is about to change or last row for id.  */
        if      last.at_risk 
                then do;
            end = date; 
            output; 
                    end;                     
Run;