Flexible Survival Modeling in SAS

Flexible Survival Modeling in SAS
beyond LIFETEST and PHREG
Presented to Nova Scotia Sas Users Group meeting, Feb 22, 2013
By Ron Dewar – Dalhousie University and Cancer Care Nova Scotia
Flexible survival modeling:
today’s objectives
• Introduce time-to-event analysis
• Survival analysis in sas
• Survival modeling - some recent
developments
• Availability of software (stata, R)
• Progress in converting to sas macros:
stata stpm2, predict, rcsgen
• The road ahead
Time-to-Event
• Duration from start to event for each subject
• Status at time (experienced event or still at risk)
• Non-informative censoring: censoring does not
change risk of eventually experiencing event
• Covariate patterns among subjects at risk (at the
time of an event)
• Other aspects:
left truncation (delayed entry)
attained age as time scale
fixed or time-varying covariates
strata
informative censoring (competing risks)
Lifetest, Phreg
• Lifetest
plotted output step/smoothed (survival, hazard)
life table estimates
significance testing between strata
• Phreg (cox regression)
left truncation
covariates (numeric and categorical), strata,
Wald tests, LR tests, AIC, BIC
plotted output(survival, hazard as step functions)
regression diagnostics
Lifetest, Phreg (cont.)
• Covariate time-dependency is common and
(maybe) more interesting
• Hazard Ratio (HR) is difficult to interpret at an
individual level
• Interest in other survival functions – hazard,
hazard differences, survival differences, relative
survival, cumulative hazard, crude probability (of
event)
• Parametric representation of survival functions
and time-dependency relations (out of sample
prediction)
Royston – Parmar survival model
2002 Statistics in Medicine 21: 2175–2197
• Cumulative hazard scale – equiv. to hazard scale if
no time-dependencies in covariates
• Restricted cubic splines for cum. hazard
• Implemented in Stata 11 as Stpm2 (model fitting)
and Predict (post-estimation)
• Similar (?) implementation in R
• ‘cure’ models, left truncation, covariate timedependency, strata, relative survival (excess
hazard), net survival, other scales
Development plan, resources
• Stata code and academic papers
• Email support from module author
• Replication of all features may not be feasible
(limited programming resources, obscure stata
features)
• Basic functionality that replicates results
• SAS code that can be used, understood,
modified, enhanced by collaborators
Proportional Hazards Model
Breast cancer survival with proportional hazards
Ods pdf file = “&loc.\doc\breast2004\cox regression.pdf”;
proc phreg data = _events_;
class sstage (ref = first);
model years*_death_(0) = sstage age1 age2 age3;
title 'Breast cancer survival, 2004 – 2010, Nova Scotia’;
title2 ‘followed to end of 2011’
title3 'Proportional Hazards model with stage, age';
run;
Ods pdf close;
PHREG output
…
Number of Observations Read
Number of Observations Used
Total
5475
…
5475
5475
Percent
Event Censored Censored
830
4645
84.84
PHREG output
Parameter
Parameter DF Estimate
sstage II 1 0.77412
sstage III 1 1.72777
sstage IV 1 3.23040
age1
1 0.18070
age2
1 0.84798
age3
1 1.58877
Standard
Error Chi-Square
0.10221
57.3652
0.10591 266.1493
0.10948 870.6004
0.12381
2.1300
0.11689
52.6287
0.11833 180.2785
Pr > ChiSq
<.0001
<.0001
<.0001
0.1444
<.0001
<.0001
Outline of analysis steps
R-P model
• Create ‘standard’ dataset: dataset name, key
variable names are fixed (%sas_stset)
• Describe and fit model (%sas_stpm2)
• Estimate functions of fitted model parameters
(%predict)
• plot predicted functions (eg, with Proc SGPlot)
Fit above model using stpm2()
• 3 stage and age binary variables, hazard scale, 5
df for baseline
• Stata command line
Stpm2 st2 st3 st4 age1 age2 age3, scale(hazard) df(5)
• Sas macro call
%Sas_stmp2( st2 st3 st4 age1 age2 age3, scale=hazard, df = 5);
Stpm2: baseline knots
• Log cumulative hazard is parameterised with
restricted cubic spline functions:
array z(*) rcs1 - rcsm < m spline variables> ;
array k(*) < m knot values >;
z(1) = y
* log time to event;
do j = 2 to m ;
phi = (k(m) - k(j) )/(k(m) - k(1) );
z(j) = ( y > k(j) )*( y - k(j) )**3
- phi*( y > k(1) )*( y - k(1) )**3
- (1 - phi)*( y > k(m) )*( y - k(m) )**3;
end;
How many knots to use?
Where to put them?
• Too few: unrealistic representation of hazard
• Too many: over-parameterisation. Unrealistic lumps
and bumps
• AIC and BIC may be helpful. LR tests are not. models
are not nested
• Some subject matter knowledge can be helpful
• Choice of position probably doesn’t matter too much
• ‘standard’ positions : centile points of cumulative
distribution of times of non-censored events
Effect of choice df
interior
knots for
baseline
hazard
1
2
3
4
5
6
7
8
PHREG
AIC
5171.4
5136.8
5136.5
5127.9
5124.9
5119.2
5106.4
5104.1
BIC
5224.2
5214.2
5222.6
5222.5
5228.2
5231.1
5226.9
5233.2
Hazard Ratio estimates
stage II stage III stage Iv
2.2
5.6
24.5
2.2
5.6
25.3
2.2
5.6
25.4
2.2
5.6
25.4
2.2
5.6
25.4
2.2
5.6
25.4
2.2
5.6
25.4
2.2
5.6
25.4
2.2
5.6
25.3
Programming in %sas_stpm2()
• Describe model in macro call
• Internal macro strings drive subsequent
processing:
•
•
•
•
•
•
•
compute spline functions
1st derivatives
orthogonalisation
Define linear predictor, log likelihood
derive initial values for optimisation
fit model (maximum likelihood with proc nlmixed)
save results for later processing
Key macro strings
• _null_ data step to build macro strings
• call symput(‘macro_var’, string)
• Linear predictor:
independent variables
parameters to be estimated
• Log likelihood:
function to be maximised
linear predictor
1st derivative of linear predictor
censor indicator
Linear predictor, Likelihood
%Sas_stmp2( st2 st3 st4 age1 age2 age3,
scale=hazard, df = 5);
Linear predictor: &xb.
cons*_cons + st2*_st2 + st3*_st3 + st4*_st4 + age1*_age1 +
age2*_age2 + age3*_age3 + rcs1*_rcs1 + rcs2*_rcs2 +
rcs3*_rcs3 + rcs4*_rcs4 + rcs5*_rcs5
1st derivative: &dxb.
rcs1*_drcs1 + rcs2*_drcs2 + rcs3*_drcs3 + rcs4*_drcs4 +
rcs5*_drcs5
Log likelihood:
_death_*((&dxb.) + &xb.) – exp(&xb.)
Linear predictor
Covariates:
xb = ifc (&int., 'cons*_cons + ', ' ');
do _i_ = 1 to &n_cov.;
var = scan("&covar.",_i_);
xb = trim(xb)||' '||trim(var)||'*_'||trim(var)||' + ' ;
end;
Splines:
do _i_ = 1 to &df.;
xb = trim(xb) ||' rcs'||put(_i_,1.)||'*'
||'_rcs'||put(_i_,1.)|| ifc(_i_< &df.," + ", " ");
end;
Example: colon cancer
*
data must be sorted by unique ID;
proc sort data = example;
by pid;
run;
*
set up a standardised survival dataset;
%sas_stset(example, censor(0), years , pid ) ;
*
fit model of interest;
%sas_stpm2(st1 st2 st3 nsex, scale=hazard, df=3 );
*
predicted hazard, survival functions for IIb cases;
%predict(haz, hazard, at = st2:1 zero);
%predict(surv, survival, at = st2:1 zero);
Example: time-varying covariate
%sas_stpm2(st1 st2 st3 nsex, scale=hazard, df=3,
tvc= st2 st3 ,
dftvc= st2:2 1 );
*
hazard prediction;
%predict(haz1, hazard, at = st2:1 zero);
*
Hazard ratio prediction;
%predict(hr1, hratio,
hrnum = st2:1 zero,
hrdenom= st2:0 zero);
Example 2: time to initiation of chronic opiod
use in new cancer patients
•
•
•
•
•
•
t0: date of new cancer diagnosis
t1: date of initiation of chronic opiod pain medication
Censor: death, end of study period (or 365 days)
Tier: cancer type grouped by 5-year survival probability
Age: 10-year age groups
Other covariates: year of diagnosis, urban/rural, sex
%sas_stpm2(t2 t3 a1 a2 a3 a4 a5 a6 nsex nurb y,
scale=hazard,
df=3,
tvc= a2 a6,
dftvc = 2);
Example 2
%macro int(row =, col =, sel = );
…
%predict(surv, survival, at = &sel. nsex:1 nurb:1 y:3 zero);
…
%mend;
And then, each for of the 21 combinations of 3 tiers X 7 age
groups:
…
%int( row = t2, col = ag2, sel = a1:1 t2:1);
%int( row = t3, col = ag2, sel = a1:1 t3:1);
…
The road ahead
• Documentation (!no, really?)
• Consistency checking
• Confidence intervals for cumulative functions
(survival, cumulative hazard)
• Out of sample estimation is inefficient
• Other survival scales (cumulative log odds,
probit…)
• Cure models
• Stratified analysis
• Competing risks framework
The future
• Use of an optimsation routine that permits
analytic 1st and 2nd derivatives (gradient &
hessian)
more efficient prediction
out of sample prediction
• Re-code string modification in %predict()