I was trying for a Cumulative Incidence graph. Please correct me.
options nodate nonumber;
data sj.data;
infile datalines dsd truncover;
input @1 SEQ 2. @4 ARMS $6. @10 armcode 2. @12 event 1. @14 mon 15. ;
datalines;
01 Dose1 1 0 3.8107752956636
02 Dose1 1 0 2.66097240473062
03 Dose1 1 0 2.43101182654402
04 Dose1 1 0 2.20105124835742
05 Dose1 1 0 1.44546649145861
;
ods output survivalplot = kmdata;
proc lifetest data = test;
time mon * event(1);
strata arms;
run;
data kmdata2;
set kmdata;
survival2 = (1-survival);
censor2 = (1-censored);
run;
proc template;
define statgraph SurvivalPlot;
begingraph / designwidth=8in designheight=5in;
entrytitle 'Cumulative Incidence Graph'/ textattrs=(size=12);
layout lattice;
layout overlay / xaxisopts =(Label = "Months (Time)" type=linear labelattrs=(size=8pt weight=bold) tickvalueattrs=(size=9pt weight=bold) linearopts=(viewmin=0 viewmax=12 tickvaluelist=(0 2 4 6 8 10 12)))
yaxisopts=(Label = "Cumulative Incidence" linearopts=(viewmin=0 viewmax=100) labelattrs=(size=8pt weight=bold) tickvalueattrs=(size=9pt weight=bold) linearopts=(viewmin=0 viewmax = 1.0 tickvaluelist=( 0.0 0.2 0.4 0.6 0.8 1.0)));
stepplot x=mon y = survival2 / group=stratum lineattrs=(thickness = 3.0 pattern=solid color = orange) name='s';
scatterplot x=mon y = censor2 / GROUP=stratum name='c' markerattrs=(symbol=plus size=8);
mergedlegend "c" "s" / location=inside halign=right valign=top order=columnmajor down=2 border=false valueattrs=(size=8pt) pad=(top=5 bottom=5);
endlayout;
layout overlay;
entry halign=left 'N at Risk' /pad=(left=0 ) valign=bottom textattrs=(size=8pt);
endlayout;
blockplot x=tatrisk block=atrisk / class=stratum display=(values label) valuehalign=start valueattrs=(size=8) labelattrs=(size=8);
endlayout;
endgraph;
end;
run;
proc sgrender data = kmdata2 template = survivalplot;
run;
Here are warnings which are shown when I run my codes.
376 options nodate nonumber;
377 ods graphics on / noborder;
378 ods output survivalplot = kmdata;
381 proc lifetest data = test;
382 time prog_mon * prog_event(1);
383 strata arms;
384 run;
NOTE: The LOGLOG transform is used to compute the confidence limits for the
quartiles of the survivor distribution. To suppress using this transform,
specify CONFTYPE=LINEAR in the PROC LIFETEST statement.
NOTE: Variable Stratum already exists on file KMDATA, using Stratum2 instead.
NOTE: The homogeneity tests across strata were omitted since there is only one
stratum.
NOTE: The data set KMDATA has 6 observations and 8 variables.
NOTE: The PROCEDURE LIFETEST printed page 1.
NOTE: PROCEDURE LIFETEST used (Total process time):
real time 2.41 seconds
cpu time 0.11 seconds
385
386 data kmdata2;
387 set kmdata;
388 survival2 = (1-survival);
389 censor2 = (1-censored);
390 run;
NOTE: Missing values were generated as a result of performing an operation on
missing values.
Each place is given by: (Number of times) at (Line):(Column).
6 at 389:14
NOTE: There were 6 observations read from the data set KMDATA.
NOTE: The data set KMDATA2 has 6 observations and 10 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
391
392 proc template;
393 define statgraph SurvivalPlot;
394 begingraph / designwidth=8in designheight=5in;
395 entrytitle 'Cumulative Incidence Graph'/
395 ! textattrs=(size=12);
396 layout lattice;
397 layout overlay / xaxisopts =(Label = "Months (Time)"
397 ! type=linear labelattrs=(size=8pt weight=bold)
397 ! tickvalueattrs=(size=9pt weight=bold) linearopts=(viewmin=0
397 ! viewmax=12 tickvaluelist=(0 2 4 6 8 10 12)))
398 yaxisopts=(Label = "Cumulative Incidence" linearopts=(viewmin=0
398 ! viewmax=100) labelattrs=(size=8pt weight=bold)
398 ! tickvalueattrs=(size=9pt weight=bold) linearopts=(viewmin=0 viewmax =
398 ! 1.0 tickvaluelist=( 0.0 0.2 0.4 0.6 0.8 1.0)));
399 stepplot x=mon y = survival2 / group=stratum
The SAS System
399 ! lineattrs=(thickness = 3.0 pattern=solid color = orange) name='s';
400 scatterplot x=mon y = censor2 / GROUP=stratum name='c'
400 ! markerattrs=(symbol=plus size=8);
401 mergedlegend "c" "s" / location=inside halign=right valign=top
401 ! order=columnmajor down=2 border=false valueattrs=(size=8pt)
401 ! pad=(top=5 bottom=5);
402 endlayout;
403 layout overlay;
404 entry halign=left 'N at Risk' /pad=(left=0 ) valign=bottom
404 ! textattrs=(size=8pt);
405 endlayout;
406 blockplot x=tatrisk block=atrisk / class=stratum display=(values
406 ! label) valuehalign=start valueattrs=(size=8) labelattrs=(size=8);
407 endlayout;
408 endgraph;
409 end;
NOTE: Overwriting existing template/link: SurvivalPlot
NOTE: STATGRAPH 'SurvivalPlot' has been saved to: SASUSER.TEMPLAT
410 run;
NOTE: PROCEDURE TEMPLATE used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
411
412 proc sgrender data = kmdata2 template = survivalplot;
413 run;
WARNING: The stepplot statement named 's' will not be drawn because one or more
of the required arguments were not supplied.
WARNING: The scatterplot statement named 'c' will not be drawn because one or
more of the required arguments were not supplied.
WARNING: The blockplot statement will not be drawn because one or more of the
required arguments were not supplied.
WARNING: The stepplot statement named 's' will not be drawn because one or more
of the required arguments were not supplied.
WARNING: The scatterplot statement named 'c' will not be drawn because one or
more of the required arguments were not supplied.
WARNING: The blockplot statement will not be drawn because one or more of the
required arguments were not supplied.
NOTE: There were 6 observations read from the data set KMDATA2.
NOTE: PROCEDURE SGRENDER used (Total process time):
real time 0.19 seconds
cpu time 0.06 seconds
Currently I am not getting anything in my graph.
Please let me know what exactly I am missing here
I think that you want to repost the data step with the data.
Apparently some line feeds were dropped and the step 1) cannot be run as posted and 2) may have commingled the values of the first and last variables.
The key bit I think is here
proc sgrender data = sj.kmdata2
You use a data set in the SJ library but your code above does not create it. So you are likely using a data set missing the variables you think you created to plot with. Try removing the SJ. from the data=.
Then go back to your Lifetest output and see if it is correct. The bit about the variable already existing may mean the lifetest added a different strata variable and you may want to use that one in the plots.
Your template code is referring to variables that don't exist in your dataset (TATRISK, MON) so it cannot make the graphs the way the template has them laid out.
proc template;
define statgraph SurvivalPlot;
begingraph / designwidth=8in designheight=5in;
entrytitle 'Cumulative Incidence Graph'/ textattrs=(size=12);
layout lattice;
layout overlay / xaxisopts =(Label = "Months (Time)" type=linear labelattrs=(size=8pt weight=bold) tickvalueattrs=(size=9pt weight=bold) linearopts=(viewmin=0 viewmax=12 tickvaluelist=(0 2 4 6 8 10 12)))
yaxisopts=(Label = "Cumulative Incidence" linearopts=(viewmin=0 viewmax=100) labelattrs=(size=8pt weight=bold) tickvalueattrs=(size=9pt weight=bold) linearopts=(viewmin=0 viewmax = 1.0 tickvaluelist=( 0.0 0.2 0.4 0.6 0.8 1.0)));
stepplot x=time y = survival2 / group=stratum lineattrs=(thickness = 3.0 pattern=solid color = orange) name='s';
scatterplot x=time y = censor2 / GROUP=stratum name='c' markerattrs=(symbol=plus size=8);
mergedlegend "c" "s" / location=inside halign=right valign=top order=columnmajor down=2 border=false valueattrs=(size=8pt) pad=(top=5 bottom=5);
endlayout;
layout overlay;
entry halign=left 'N at Risk' /pad=(left=0 ) valign=bottom textattrs=(size=8pt);
endlayout;
blockplot x=time block=atrisk / class=stratum display=(values label) valuehalign=start valueattrs=(size=8) labelattrs=(size=8);
endlayout;
endgraph;
end;
run;
proc sgrender data = kmdata2 template = survivalplot;
run;
I would like to add that you are not currently making a cumulative incidence plot however, but a 1-survival (failure rate) plot. There are options in PROC LIFETEST to generate actual CIF function output (EVENTCODE option in the TIME statement).
Also, obligatory link to my NEWSURV macro that I've shared that can do all of these kinds of graphs if you would like to try it: NEWSURV Link
This is how different 1-KM vs CIF can be. The top is 1-KM the bottom is CIF:
The macro (%newsurv) will do them for you if you want to have them with a macro call like:
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;
%newsurv(data=bmt,time=ftime,cens=status,class=diagnosis, method=cif,ev_vl=1, summary=0, gpath=~/ibm/,
risklist=0 to 2500 by 500);
The code that runs in the background would look something like this (it calculates the N at risk manually):
proc lifetest data=bmt alpha=0.05 alphaqt=0.05 cifvar error=aalen
outcif=_surv (where=((event>. or t1=0 or c1=1))
rename=(stratum=stratumnum ftime=t1 cif=s1 censored=c1 cif_lcl=lcl1 cif_ucl=ucl1 variance=vcif)
keep=cif ftime censored event atrisk cif_lcl cif_ucl variance stratum)
conftype=LOG;
strata diagnosis;
time ftime * status(0) / failcode=1;
run;
data _splot;
set _surv;
by stratumnum;
array _risktimes_ {6} (0, 500, 1000, 1500, 2000, 2500);
retain _ncens _nevents _lagncens _lagnevents;
if first.stratumnum then do;
_ncens=0;
_nevents=0;
_lagncens=0;
_lagnevents=0;
_count_=1;
end;
if _count_ le dim(_risktimes_) then do;
if t1 <=_risktimes_{_count_} then do;
if event>. then _nevents=_nevents+event;
if c1>. then _ncens=_ncens+c1;
end;
else do;
if event>. then _lagnevents=_lagnevents+event;
if c1>. then _lagncens=_lagncens+c1;
end;
end;
if _count_ le dim(_risktimes_) then do;
if t1 >=_risktimes_(_count_) then do until(x=1);
tatrisk=_risktimes_(_count_);
time=tatrisk;
call missing(event, c1);
output;
_nevents=_nevents+_lagnevents;
_ncens=_lagncens+_ncens;
_lagnevents=0;
_lagncens=0;
_count_+1;
if _count_>dim(_risktimes_) then x=1;
else if t1 < _risktimes_(_count_) then x=1;
else x=0;
end;
if last.stratumnum then do i=_count_ to dim(_risktimes_);
tatrisk=_risktimes_(_count_);
time=tatrisk;
atrisk=0;
call missing(event, c1);
output;
_nevents=_nevents+_lagnevents;
_ncens=_lagncens+_ncens;
_lagnevents=0;
_lagncens=0;
end;
end;
keep tatrisk time stratumnum atrisk event c1 t1 _count_ _nevents _ncens _lagnevents _lagncens;
rename c1=censored;
run;
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.