Resources

PROC LIFETEST Template (Revised for SAS Global Forum 2013)

/****************************************************************/
/*          S A S   S A M P L E   L I B R A R Y                 */
/*                                                              */
/*    NAME: TEMPLFT2                                            */
/*   TITLE: PROC LIFETEST Template                              */
/*          (Revised for SAS Global Forum 2013)                 */
/* PRODUCT: STAT                                                */
/*  SYSTEM: ALL                                                 */
/*    KEYS: graphics, ods, survival analysis, Kaplan-Meier      */
/*   PROCS:                                                     */
/*    DATA:                                                     */
/*                                                              */
/* SUPPORT: saswfk                UPDATE: February 5, 2013      */
/*     REF: ods graphics                                        */
/*    MISC:                                                     */
/*   NOTES: This sample provides templates for the PROC         */
/*          LIFETEST survival plot that are more modular and    */
/*          easier to modify than the default templates.        */
/****************************************************************/

%macro SurvivalTemplateRestore;

   %global TitleText0 TitleText1 TitleText2 yOptions xOptions tips
           tipl groups bandopts gridopts blockopts censored censorstr;

   %let TitleText0 = METHOD " Survival Estimate";
   %let TitleText1 = &titletext0 " for " STRATUMID;
   %let TitleText2 = &titletext0 "s";         /* plural: Survival Estimates */

   %let yOptions   = label="Survival Probability" shortlabel="Survival"
                     linearopts=(viewmin=0 viewmax=1
                                 tickvaluelist=(0 .2 .4 .6 .8 1.0));

   %let xOptions   = shortlabel=XNAME offsetmin=.05
                     linearopts=(viewmax=MAXTIME tickvaluelist=XTICKVALS
                                 tickvaluefitpolicy=XTICKVALFITPOL);

   %let tips       = rolename=(_tip1= ATRISK _tip2=EVENT)
                     tiplabel=(_tip1="Number at Risk" _tip2="Observed Events")
                     tip=(x y _tip1 _tip2);
   %let tipl       = tiplabel=(y="Survival Probability");

   %let groups     = group=STRATUM index=STRATUMNUM;

   %let bandopts   = &groups modelname="Survival";

   %let gridopts   = autoalign=(TOPRIGHT BOTTOMLEFT TOP BOTTOM)
                     border=true BackgroundColor=GraphWalls:Color Opaque=true;

   %let blockopts  = repeatedvalues=true display=(label values) valuehalign=start
                     valuefitpolicy=truncate labelposition=left
                     labelattrs=GRAPHVALUETEXT valueattrs=GRAPHDATATEXT(size=7pt) 
                     includemissingclass=false;

   %let censored   = markerattrs=(symbol=plus);
   %let censorstr  = "+ Censored";

   %macro SurvivalTemplate;
      %local outside _tmpnum;
      proc template;
        %do outside = 0 %to 1;
          define statgraph Stat.Lifetest.Graphics.ProductLimitSurvival%scan(2,2-&outside);
             dynamic NStrata xName plotAtRisk %if %nrbquote(&censored) ne %then plotCensored;
                plotCL plotHW plotEP labelCL labelHW labelEP maxTime xtickVals xtickValFitPol 
                rowWeights method StratumID classAtRisk plotBand plotTest GroupName yMin 
                Transparency SecondTitle TestName pValue _byline_ _bytitle_ _byfootnote_;
             BeginGraph;

             if (NSTRATA=1)
                if (EXISTS(STRATUMID)) entrytitle &titletext1;
                else                   entrytitle &titletext0;
                endif;

                %if not &outside %then if (PLOTATRISK);
                   entrytitle "With Number of Subjects at Risk" / textattrs=GRAPHVALUETEXT;
                %if not &outside %then %do; endif; %end;

                %AtRiskLatticeStart
                layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                   %singlestratum
                endlayout;
                %AtRiskLatticeEnd

             else
                entrytitle &titletext2;
                if (EXISTS(SECONDTITLE))
                   entrytitle SECONDTITLE / textattrs=GRAPHVALUETEXT;
                endif;

                %AtRiskLatticeStart
                layout overlay / xaxisopts=(&xoptions) yaxisopts=(&yoptions);
                   %multiplestrata
                endlayout;
                %AtRiskLatticeEnd(%str(class=CLASSATRISK))

             endif;

             if (_BYTITLE_) entrytitle _BYLINE_ / textattrs=GRAPHVALUETEXT;
             else if (_BYFOOTNOTE_) entryfootnote halign=left _BYLINE_; endif;
             endif;
             EndGraph;
          end;
        %end;
      run;
   %mend;

   %macro entry_p;
      if (PVALUE < .0001)
         entry TESTNAME " p " eval (PUT(PVALUE, PVALUE6.4));
      else
         entry TESTNAME " p=" eval (PUT(PVALUE, PVALUE6.4));
      endif;
   %mend;

   %macro SingleStratum;
      if (PLOTHW=1 AND PLOTEP=0)
         bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHCONFIDENCE
            name="HW" legendlabel=LABELHW;
      endif;
      if (PLOTHW=0 AND PLOTEP=1)
         bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHCONFIDENCE
            name="EP" legendlabel=LABELEP;
      endif;
      if (PLOTHW=1 AND PLOTEP=1)
         bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHDATA1 datatransparency=.55
            name="HW" legendlabel=LABELHW;
         bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME /
            modelname="Survival" fillattrs=GRAPHDATA2
            datatransparency=.55 name="EP" legendlabel=LABELEP;
      endif;
      if (PLOTCL=1)
         if (PLOTHW=1 OR PLOTEP=1)
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
               modelname="Survival" display=(outline)
               outlineattrs=GRAPHPREDICTIONLIMITS name="CL" legendlabel=LABELCL;
         else
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME /
               modelname="Survival" fillattrs=GRAPHCONFIDENCE name="CL"
               legendlabel=LABELCL;
         endif;
      endif;

      stepplot y=SURVIVAL x=TIME / name="Survival" &tips legendlabel="Survival";

      if (PLOTCENSORED=1)
         scatterplot y=CENSORED x=TIME / &censored &tipl
            name="Censored" legendlabel="Censored";
      endif;

      if (PLOTCL=1 OR PLOTHW=1 OR PLOTEP=1)
         discretelegend "Censored" "CL" "HW" "EP" / location=outside
            halign=center;
      else
         if (PLOTCENSORED=1)
            discretelegend "Censored" / location=inside
                                        autoalign=(topright bottomleft);
         endif;
      endif;
      %if not &outside %then %do;
         if (PLOTATRISK=1)
            innermargin / align=bottom;
               blockplot x=TATRISK block=ATRISK / &blockopts;
            endinnermargin;
         endif;
      %end;
   %mend;

   %macro MultipleStrata;
     if (PLOTHW)
         bandplot LimitUpper=HW_UCL LimitLower=HW_LCL x=TIME / &bandopts
                  datatransparency=Transparency;
      endif;
      if (PLOTEP)
         bandplot LimitUpper=EP_UCL LimitLower=EP_LCL x=TIME / &bandopts
                  datatransparency=Transparency;
      endif;
      if (PLOTCL)
         if (PLOTBAND)
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                     display=(outline);
         else
            bandplot LimitUpper=SDF_UCL LimitLower=SDF_LCL x=TIME / &bandopts
                     datatransparency=Transparency;
         endif;
      endif;

      stepplot y=SURVIVAL x=TIME / &groups name="Survival" &tips;

      if (PLOTCENSORED)
         scatterplot y=CENSORED x=TIME / &groups &tipl &censored;
      endif;

      %if not &outside  %then %do;
         if (PLOTATRISK=1)
            innermargin / align=bottom;
               blockplot x=TATRISK block=ATRISK / class=CLASSATRISK &blockopts;
            endinnermargin;
         endif;
         %end;

      DiscreteLegend "Survival" / title=GROUPNAME location=outside;

      if (PLOTCENSORED)
         if (PLOTTEST)
            layout gridded / rows=2 &gridopts;
               entry &censorstr;
               %entry_p
            endlayout;
         else
            layout gridded / rows=1 &gridopts;
               entry &censorstr;
            endlayout;
         endif;
      else
         if (PLOTTEST)
            layout gridded / rows=1 &gridopts;
               %entry_p
            endlayout;
         endif;
      endif;
   %mend;

   %macro AtRiskLatticeStart;
      %if &outside %then %do;
         layout lattice / rows=2 rowweights=ROWWEIGHTS
                          columndatarange=union rowgutter=10;
         cell;
      %end;
   %mend;

   %macro AtRiskLatticeEnd(class);
      %if &outside %then %do;
         endcell;
         cell;
            layout overlay / walldisplay=none xaxisopts=(display=none);
               blockplot x=TATRISK block=ATRISK / &class &blockopts;
            endlayout;
         endcell;
      endlayout;
      %end; 
   %mend;

%SurvivalTemplate
%mend;