Hi everyone. I'm trying to add an at-risk table to my Kaplan-Meier curves. I'm using the survival macros code found here.
If I do not use the "outside" option, everything aligns nicely.
* Bring in macro; %ProvideSurvivalMacros %let tatters = textattrs=(size=14pt); %let TitleText0 = "3-Year Post-Recurrence Survival" / textattrs=(size=14pt); %let TitleText1 = &titletext0 ; %let TitleText2 = &titletext0 ; %let yoptions = label='Overall Survival Probability' labelattrs=(size=12pt) linearopts=(viewmin=0 viewmax=1 tickvaluelist=(0 .2 0.4 0.6 0.8 1)); %let xoptions = label='Months from Recurrence' labelattrs=(size=12pt) linearopts=(viewmin=0 viewmax=24 tickvaluelist=(0 6 12 18 24));; %let StepOpts = lineattrs=(thickness=1); %let LegendOpts = title=' ' location=inside across=1 autoalign=(TopRight) border=FALSE; %let GraphOpts = attrpriority=none DataLinePatterns=(Solid); * 24-Apr-2024: Add number at risk; %let AtRiskOpts = valueattrs=(size=10pt) ; %CompileSurvivalTemplates; ods select survivalplot; proc lifetest data=post plots=survival(atrisk(maxlen=20 /*outside*/)=0 to 24 by 6); format group $recur_two.; time PRS3YrMonths*death3yr(0); strata group; run; ods select all;
However, if I request it to be outside the plot area, it is no longer aligned.
* Bring in macro; %ProvideSurvivalMacros %let tatters = textattrs=(size=14pt); %let TitleText0 = "3-Year Post-Recurrence Survival" / textattrs=(size=14pt); %let TitleText1 = &titletext0 ; %let TitleText2 = &titletext0 ; %let yoptions = label='Overall Survival Probability' labelattrs=(size=12pt) linearopts=(viewmin=0 viewmax=1 tickvaluelist=(0 .2 0.4 0.6 0.8 1)); %let xoptions = label='Months from Recurrence' labelattrs=(size=12pt) linearopts=(viewmin=0 viewmax=24 tickvaluelist=(0 6 12 18 24));; %let StepOpts = lineattrs=(thickness=1); %let LegendOpts = title=' ' location=inside across=1 autoalign=(TopRight) border=FALSE; %let GraphOpts = attrpriority=none DataLinePatterns=(Solid); * 24-Apr-2024: Add number at risk; %let AtRiskOpts = valueattrs=(size=10pt) ; %CompileSurvivalTemplates; ods select survivalplot; proc lifetest data=post plots=survival(atrisk(maxlen=20 outside)=0 to 24 by 6); format group $recur_two.; time PRS3YrMonths*death3yr(0); strata group; run; ods select all;
In the macro code, while messing around with the AtRiskLattice sections to try and fix it, I removed "xaxisopts=(display=none)." This did not fix it, but did illuminate the issue a bit. Apparently the axis for the at-risk table is not the same as the overall x-axis:
Does anyone have any idea how to get these to align?
Please let me know if I can provide more info.
You could try alternative way to get it .
proc format;
value grpLabel 1='ALL' 2='AML low risk' 3='AML high risk';
run;
data BMT;
input DIAGNOSIS Ftime Status Gender@@;
label Ftime="Days";
format Diagnosis grpLabel.;
datalines;
1 2081 0 1 1 1602 0 1
1 1496 0 1 1 1462 0 0
1 1433 0 1 1 1377 0 1
1 1330 0 1 1 996 0 1
1 226 0 0 1 1199 0 1
1 1111 0 1 1 530 0 1
1 1182 0 0 1 1167 0 0
1 418 2 1 1 383 1 1
1 276 2 0 1 104 1 1
1 609 1 1 1 172 2 0
1 487 2 1 1 662 1 1
1 194 2 0 1 230 1 0
1 526 2 1 1 122 2 1
1 129 1 0 1 74 1 1
1 122 1 0 1 86 2 1
1 466 2 1 1 192 1 1
1 109 1 1 1 55 1 0
1 1 2 1 1 107 2 1
1 110 1 0 1 332 2 1
2 2569 0 1 2 2506 0 1
2 2409 0 1 2 2218 0 1
2 1857 0 0 2 1829 0 1
2 1562 0 1 2 1470 0 1
2 1363 0 1 2 1030 0 0
2 860 0 0 2 1258 0 0
2 2246 0 0 2 1870 0 0
2 1799 0 1 2 1709 0 0
2 1674 0 1 2 1568 0 1
2 1527 0 0 2 1324 0 1
2 957 0 1 2 932 0 0
2 847 0 1 2 848 0 1
2 1850 0 0 2 1843 0 0
2 1535 0 0 2 1447 0 0
2 1384 0 0 2 414 2 1
2 2204 2 0 2 1063 2 1
2 481 2 1 2 105 2 1
2 641 2 1 2 390 2 1
2 288 2 1 2 421 1 1
2 79 2 0 2 748 1 1
2 486 1 0 2 48 2 0
2 272 1 0 2 1074 2 1
2 381 1 0 2 10 2 1
2 53 2 0 2 80 2 0
2 35 2 0 2 248 1 1
2 704 2 0 2 211 1 1
2 219 1 1 2 606 1 1
3 2640 0 1 3 2430 0 1
3 2252 0 1 3 2140 0 1
3 2133 0 0 3 1238 0 1
3 1631 0 1 3 2024 0 0
3 1345 0 1 3 1136 0 1
3 845 0 0 3 422 1 0
3 162 2 1 3 84 1 0
3 100 1 1 3 2 2 1
3 47 1 1 3 242 1 1
3 456 1 1 3 268 1 0
3 318 2 0 3 32 1 1
3 467 1 0 3 47 1 1
3 390 1 1 3 183 2 0
3 105 2 1 3 115 1 0
3 164 2 0 3 93 1 0
3 120 1 0 3 80 2 1
3 677 2 1 3 64 1 0
3 168 2 0 3 74 2 0
3 16 2 0 3 157 1 0
3 625 1 0 3 48 1 0
3 273 1 1 3 63 2 1
3 76 1 1 3 113 1 0
3 363 2 1
;
run;
ods select none;
ods output SurvivalPlot=SurvivalPlot;
proc lifetest data=bmt plots=survival(atrisk=0 to 2500 by 500);
time ftime*Status(0);
strata diagnosis;
run;
ods select all;
title '缓解概率';
proc sgplot data=SurvivalPlot;
step x=Time y=Survival / group=Stratum lineattrs=(pattern=solid) name='a' ;
scatter x=Time y=Censored /group=Stratum markerattrs=(symbol=plus ) ;
xaxistable atrisk / x=tatrisk class=stratum colorgroup=stratum valueattrs=(weight=bold);
xaxis label='天数';
yaxis label='存活概率';
keylegend 'a' / across=1 location=inside position=ne title='' ;
inset '+ Censored' / position=sw border;
run;
You could try alternative way to get it .
proc format;
value grpLabel 1='ALL' 2='AML low risk' 3='AML high risk';
run;
data BMT;
input DIAGNOSIS Ftime Status Gender@@;
label Ftime="Days";
format Diagnosis grpLabel.;
datalines;
1 2081 0 1 1 1602 0 1
1 1496 0 1 1 1462 0 0
1 1433 0 1 1 1377 0 1
1 1330 0 1 1 996 0 1
1 226 0 0 1 1199 0 1
1 1111 0 1 1 530 0 1
1 1182 0 0 1 1167 0 0
1 418 2 1 1 383 1 1
1 276 2 0 1 104 1 1
1 609 1 1 1 172 2 0
1 487 2 1 1 662 1 1
1 194 2 0 1 230 1 0
1 526 2 1 1 122 2 1
1 129 1 0 1 74 1 1
1 122 1 0 1 86 2 1
1 466 2 1 1 192 1 1
1 109 1 1 1 55 1 0
1 1 2 1 1 107 2 1
1 110 1 0 1 332 2 1
2 2569 0 1 2 2506 0 1
2 2409 0 1 2 2218 0 1
2 1857 0 0 2 1829 0 1
2 1562 0 1 2 1470 0 1
2 1363 0 1 2 1030 0 0
2 860 0 0 2 1258 0 0
2 2246 0 0 2 1870 0 0
2 1799 0 1 2 1709 0 0
2 1674 0 1 2 1568 0 1
2 1527 0 0 2 1324 0 1
2 957 0 1 2 932 0 0
2 847 0 1 2 848 0 1
2 1850 0 0 2 1843 0 0
2 1535 0 0 2 1447 0 0
2 1384 0 0 2 414 2 1
2 2204 2 0 2 1063 2 1
2 481 2 1 2 105 2 1
2 641 2 1 2 390 2 1
2 288 2 1 2 421 1 1
2 79 2 0 2 748 1 1
2 486 1 0 2 48 2 0
2 272 1 0 2 1074 2 1
2 381 1 0 2 10 2 1
2 53 2 0 2 80 2 0
2 35 2 0 2 248 1 1
2 704 2 0 2 211 1 1
2 219 1 1 2 606 1 1
3 2640 0 1 3 2430 0 1
3 2252 0 1 3 2140 0 1
3 2133 0 0 3 1238 0 1
3 1631 0 1 3 2024 0 0
3 1345 0 1 3 1136 0 1
3 845 0 0 3 422 1 0
3 162 2 1 3 84 1 0
3 100 1 1 3 2 2 1
3 47 1 1 3 242 1 1
3 456 1 1 3 268 1 0
3 318 2 0 3 32 1 1
3 467 1 0 3 47 1 1
3 390 1 1 3 183 2 0
3 105 2 1 3 115 1 0
3 164 2 0 3 93 1 0
3 120 1 0 3 80 2 1
3 677 2 1 3 64 1 0
3 168 2 0 3 74 2 0
3 16 2 0 3 157 1 0
3 625 1 0 3 48 1 0
3 273 1 1 3 63 2 1
3 76 1 1 3 113 1 0
3 363 2 1
;
run;
ods select none;
ods output SurvivalPlot=SurvivalPlot;
proc lifetest data=bmt plots=survival(atrisk=0 to 2500 by 500);
time ftime*Status(0);
strata diagnosis;
run;
ods select all;
title '缓解概率';
proc sgplot data=SurvivalPlot;
step x=Time y=Survival / group=Stratum lineattrs=(pattern=solid) name='a' ;
scatter x=Time y=Censored /group=Stratum markerattrs=(symbol=plus ) ;
xaxistable atrisk / x=tatrisk class=stratum colorgroup=stratum valueattrs=(weight=bold);
xaxis label='天数';
yaxis label='存活概率';
keylegend 'a' / across=1 location=inside position=ne title='' ;
inset '+ Censored' / position=sw border;
run;
Thanks so much! That worked. I have spent so much time on previous projects trying to get the macro to work - using SGPLOT is sooo much easier!
Here's what I ultimately used:
* Save output to dataset; ods select none; proc lifetest data=post plots=survival(atrisk(maxlen=20)=0 to 24 by 6); format group $recur_two.; time PRS3YrMonths*death3yr(0); strata group; ods output survivalplot=postplot; run; ods select all; * Only keep <=24 months; data postplot2; set postplot; if tatrisk <= 24; run; title height=14pt 'Post-recurrence Survival' ; proc sgplot data=postplot2; step x=Time y=Survival / group=Stratum lineattrs=(pattern=solid) name='a' ; scatter x=Time y=Censored /group=Stratum markerattrs=(symbol=plus ) ; xaxistable atrisk / x=tatrisk class=stratum colorgroup=stratum valueattrs=(size=10pt) ; xaxis label='Months from Recurrence' values=(0 6 12 18 24) labelattrs=(size=12pt) valueattrs=(size=10pt); yaxis label='Overall Survival Probability' labelattrs=(size=12pt) valueattrs=(size=10pt); keylegend 'a' / across=1 location=inside position=ne title='' ; inset '+ Censored' / position=sw border; run; title;
And the output:
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.