Hi All,
I am producing a a Kaplan Meier plot with confidence bands using the Proc Lifetest procedure. I have successfully produced the plot and amended various aspects of the proc template (Stat.Lifetest.Graphics.ProductLimitSurvival) produced by SAS's %ProvideSurvivalMacros macro.
I need help adjusting the transparency of the confidence bands as they overlap and make elements of the plot hard to see. I have tried reading the proc template into a dataset as SAS' own documentation suggests (see: https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.4/statug/statug_kaplan_sect016.htm) and amended the datatransparency=.55 code. This is reflected in the template after the datastep, however when the proc lifetest is executed and plot produced the band transparencies don't change. I have also tried to change the dynamic variables set in the proc template and then use proc sgrender to set the value of the dynamic variable "Transparency" (as the template contains "datatransparency=Transparency"), but again the transparency doesn't change in the final plot. I have included my code below, hopefully one of you will spot something blaringly obvious, I've trawled the internet for the answer and tried everything suggested and now I'm at a loss for the resolution.
Thank you SAS community!
data _null_; %let url = //support.sas.com/documentation/onlinedoc/stat/ex_code/151; infile "http:&url/templft.html" device=url; file 'macros.tmp'; retain pre 0; input; _infile_ = tranwrd(_infile_, '&', '&'); _infile_ = tranwrd(_infile_, '<' , '<'); if index(_infile_, '</pre>') then pre = 0; if pre then put _infile_; if index(_infile_, '<pre>') then pre = 1; run; %inc 'macros.tmp' / nosource; %ProvideSurvivalMacros; **Make Changes to the template**; %let ntitles=0; %let TitleText0 = ""; /* Change the title. */ %let TitleText1 = ""; %let TitleText2 = ""; **Y Axis options**; %let yOptions = label="Kaplan-Meier Probability" linearopts=(viewmin=0 viewmax=1 tickvaluelist=(0 0.2 0.4 0.6 0.8 1)); **X Axis options**; %let xOptions = label="Chronological Age (Years)" linearopts=(viewmin=0 viewmax=14 tickvaluelist=(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)); **Set colours/pattern of the plot lines and bands**; %let GraphOpts = DataContrastColors=(green blue) DataColors=(green blue) DataLinePatterns=(ShortDash Solid) border=false opaque=false; **Set line thickness**; %let StepOpts = lineattrs=(thickness=2); **Update location of legend**; %let InsetOpts = autoalign=(BottomRight) border=true BackgroundColor=GraphWalls:Color Opaque=true; %let LegendOpts = title="Treatment:" location=outside across=3 down=1 autoalign=(Bottom); %let transparency=0; %let AtRiskOpts = labelattrs=(size=10pt) valueattrs=(size=10pt); **Updated censored marker**; %let censored = markerattrs=(symbol=circle size=7px color=black); %let censorstr = "(*ESC*){Unicode '25cf'x} Censored" / textattrs=GraphValueText(family=GraphUnicodeText:FontFamily); %let axistable = display=(label value); **Compile the template with the new modifications**; proc template; source Stat.Lifetest.Graphics.ProductLimitSurvival / file='temp.tmp'; quit; data _null_; length var stmt $ 32; infile 'temp.tmp' end=eof; input; if _n_ eq 1 then call execute('proc template;'); stmt = scan(_infile_, 1); if stmt in ('scatterplot', 'stepplot', 'bandplot') then do; var = scan(scan(_infile_, 2, '='), 1); _infile_ = tranwrd(_infile_, trim(var), cats('eval(100*',var,')')); if stmt = 'bandplot' then do; var = scan(scan(_infile_, 3, '='), 1); _infile_ = tranwrd(_infile_, trim(var), cats('eval(100*',var,')')); _infile_ = tranwrd(_infile_,'name="CL"','datatransparency=Transparency name="CL"'); _infile_ = tranwrd(_infile_,'name="HW"','datatransparency=Transparency name="HW"'); _infile_ = tranwrd(_infile_,'name="EP"','datatransparency=Transparency name="EP"'); end; end; _infile_ = tranwrd(_infile_, '0 0.2 0.4 0.6 0.8 1', '0 20 40 60 80 100'); _infile_ = tranwrd(_infile_, 'viewmax=1', 'viewmax=100'); call execute(_infile_); if eof then call execute('quit;'); run; %CompileSurvivalTemplates; %let trtopt = trta; %let trtoptn = trtan; * If there is cryo sibling data then include that; %if &cryosib. ne %then %do; * Get data; data temp0; set &dsin. (where = (paramcd = "¶mcd." and &pop="Y" &where.)); run; data temp0b; set &dsin. (where = (paramcd="&cryosib." %if &disvar. ne %then %do; and csircdgp="&disvar." %end;)); * Set the treatment group to Natural History as these are untreated siblings; * JSS 19Apr22 Updated to remove length statement; &trtopt.="Natural History"; &trtoptn.=1; run; data temp1(keep = &trtopt. &trtoptn. cnsr usubjid aval &pop trtlab ord:); set temp0 temp0b; length trtlab $200; if &trtoptn. = 1 then do; trtlab = strip(&trtopt.); ordtrt = 2; end; if &trtoptn. = 2 then do; trtlab = strip(&trtopt.); ordtrt = 1; end; run; %end; %if &cryosib. = %then %do; * Get data; data temp1 (keep = &trtopt. &trtoptn. cnsr usubjid aval &pop trtlab ord:); set &dsin.; length trtlab $200; attrib trtlab label='Treatment'; where paramcd = "¶mcd." and &pop="Y" &where.; if &trtoptn. = 1 then do; trtlab = strip(&trtopt.); ordtrt = 2; end; if &trtoptn. = 2 then do; trtlab = strip(&trtopt.); ordtrt = 1; end; run; %end; proc sort data = temp1; by ordtrt; run; * KM analysis; proc sgrender data=temp1 template=Stat.Lifetest.Graphics.ProductLimitSurvival; dynamic Transparency=0.7; run; OPTIONS NODATE NONUMBER ORIENTATION=LANDSCAPE NOBYLINE; ods noproctitle; ods graphics on / noborder; ods select SurvDiff SurvivalPlot; ODS ESCAPECHAR="~"; ods pdf file="folder_path_hidden_for_client_confidentiality_purposes" style=styles.monospace /* nogtitle nogfootnote*/; TITLE1 J=L "Protocol: Integrated Summary of Effectiveness" J=RIGHT 'Page ~{thispage} of ~{lastpage}'; TITLE2 J=L "Data Cut-Off Date: xxxxx"; TITLE3 J=L "Population: &t1"; TITLE4 J=C "Figure &t2"; TITLE5 J=C "&t3"; ods graphics on / noborder reset width=9in height=6.5in imagename="KaplanMeierPlot"; proc lifetest data=temp1 method=km outsurv=temp2 plots=(survival(cl atrisk=0 to 14 by 1 maxlen=16 atrisktick outside)) conftype=linear confband=hw; time aval*cnsr(1); strata trtlab / TEST=none; run; ods pdf close; ods graphics off; **Delete the proc lifetest templates created and stored earlier in the macro**; proc template; delete Stat.Lifetest.Graphics.ProductLimitSurvival / store=sasuser.templat; delete Stat.Lifetest.Graphics.ProductLimitSurvival2 / store=sasuser.templat; run;
Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.