【问题标题】:SAS adding new observations for longitudinal dataSAS为纵向数据添加新的观察
【发布时间】:2014-10-09 21:31:52
【问题描述】:

我在 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"

想法?

【问题讨论】:

  • 您有 ETS 许可吗?

标签: sas


【解决方案1】:

Vasja 可能一直在建议这样的东西(日期级别)作为替代方案。

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

您确定您的开始日期和结束日期正确吗?您想要的输出仍然有重叠的日期。 2 月 1 日和 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; 

【讨论】:

    【解决方案2】:

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

    如果有超过当前下一个记录的时间重叠,我不确定这种方式是否可行(通过合理的努力)。对于这种情况,您可能会更有效地将原始开始 - 结束时间间隔拆分为日级别,然后将详细信息汇总到新的时间间隔

    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;
    

    【讨论】:

    • 是的,不幸的是,除了当前-下一个记录之外,还有其他重叠。不过,您关于将时间间隔分成不同日子的建议是正确的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    相关资源
    最近更新 更多