lecture 16: regression diagnostics i proportional hazards assumption -graphical methods -regression...
TRANSCRIPT
Lecture 16: Regression Diagnostics I
Proportional Hazards Assumption -graphical methods -regression methods
Regression Diagnostics
• Most interested in testing proportional hazards assumption
• Also looking for functional form of covariates• Two types of methods– Graphical approaches– Regression approaches
Graphical Approaches
• Recall our graphical checks– Kernel smoothing– Smoothing splines
• Both will provide information about whether or not the hazards cross
• Both can be implemented in R– “muhaz” package: kernel smoothing for survival– “gss” package: smoothing splines for survival
Graphical Approaches• Consider CPHM with single binary covariate…
• This means we can also can consider the following plot…
• If hazards proportional, this should be ≈ equal to • No package in R
– Calculate NA hazard estimates for each condition at each unique time point
0
ˆ 1
0
ˆexp
ˆ1 0 lnH t Z
H t Z
h t Z h t Z
H t Z e H t Z
ln 1 ln 0 vs. H t Z H t Z t
Examples
• Lets explore the graphical and regression checks for proportional hazards– Kidney Infection data• Surgical vs. percutaneous
– BMT data• FAB classification• Methotrexate use
Survival for Kidney
Graphical Checks### KIDNEY INFECTION EXAMPLE####log cum haz plotsLibrary(Kmsurv); library(survival)
coxph(Surv(time, delta)~factor(type), data=kidney)dat1<-kidney[kidney$type==1, ]dat2<-kidney[kidney$type==2, ]fit1<-survfit(coxph(Surv(time, delta)~1, data=dat1), type="aalen")fit2<-survfit(coxph(Surv(time, delta)~1, data=dat2), type="aalen")
times<-sort(unique(kidney$time))ch1<--log(fit1$surv)ch2<--log(fit2$surv)
ch1<-c(0, ch1[1:17],ch1[17],ch1[17],ch1[18:20],ch1[20],ch1[21:23],ch1[23])ch2<-c(ch2[1:13],ch2[13],ch2[14:19],ch2[19],ch2[20],ch2[20],ch2[21:23],ch2[23],ch2[24])plot(times, log(ch2)-log(ch1), type="s", xlab="time",
ylab="log(H[t|Z=perc])-log(H[t|Z=surg])", lwd=2)lines(times, rep(0.613, length(times)), lwd=2, col=2)
Graphical Checks#Smoothing splinescath<-kid$cath[order(kid$Time)]event<-kid$d[order(kid$Time)]times<-sort(kid$Time)
library(gss)hazfit<-sshzd(Surv(times, event)~cath*times)haz<-hzdrate.sshzd(hazfit, data.frame(times=times, cath=cath))h1<-haz[cath==1]; id1<-order(h1); t1<-times[cath==1]h2<-haz[cath==0]; id2<-order(h2); t2<-times[cath==0]
plot(times[cath==0], haz[cath==0], xlim=c(0, max(times)), ylim=range(haz), xlab="Time", type="l",ylab="hazard", lwd=2, col=1)lines(times[cath==1], haz[cath==1], lwd=2, col=2)legend(0, .1, c("percutaneous","surgical"), col=1:3, lwd=2, cex=0.8)
Graphical Checks: Kidney
BMT Data
• Let’s conduct graphical checks for – French/American/British Disease classification• Recall this was significant in our original model
– Methotrexate use• Recall this was not
Survival Curves for BMT: FAB and MTX
BMT Graphical Checks: FAB
BMT Graphical Checks: MTX
Graphical Approaches
• Pretty pictures are nice and can be intuitive but…
• We generally prefer a statistical means of determining if an assumption is true
• This leads us to regression approaches
Regression Approaches
• Impose a time-dependent covariate into the model
• General idea:– If PHM is valid, time-dependent covariate will not
be significant– If time-dependent covariate is significant, then
there is “something” going on in terms of the HRs that varies over time
Introduce Time Dependent Covariate
• Create an new variable Z2(t) = Z1×g(t), where g(t) is a function of time
• We don’t know the functional form of g(t)• Try several possibilities, for example
ln
0 if specific time
at time t if specific time
0 if specific time
ln * at time t if specific time
g t t
g t t
tg t
Z t
tg t
t Z t
Binary Case
• Consider a binary covariate Z1
• Generate
• Model is:
• Hazard ratio is:
1
2 11
0 if 0
ln if 1
ZZ Z g t
g t t Z
0 1 1 2 2
0 1 2 1
exp
exp ln
h t h t Z Z
h t t Z
Z
1 2
1
1
10exp
h t Z
h t Zt
New Time Dependent Covariate
• Fit proportional hazards model with Z1, Z2(t), and estimate b1, b2
• Test local hypothesis:– H0: b2 = 0 vs. HA: b2 ≠ 0
• If you reject H0, can not assume proportional hazards
• Do this for each covariate in question
Examples
• Lets explore the regression check for proportional hazards in our two examples…
– Kidney Infection data• Surgical vs. percutaneous
– BMT data• FAB classification• Methotrexate use
Regression Check: Kidney### Kidney Example (are hazards for percutaneous and surgical proportional?)times<-sort(unique(kidney$time))kidney$id<-1:nrow(kidney)
kid.long<-expand.breakpoints(kidney, index="id", status="delta", tevent="time", breakpoints=times)
kid.long$ttype1<-log(kid.long$Tstop)*(kid.long$type-1)kid.long$ttype2<-kid.long$Tstop*(kid.long$type-1)kid.long$ttype3<-ifelse(kid.long$Tstop>7.5, (kid.long$type-1), 0)kid.long$ttype4<-ifelse(kid.long$Tstop>7.5, kid.long$Tstop*(kid.long$type-1), 0)
m1<-coxph(Surv(Tstart, Tstop, delta)~type+ttype1, data=kid.long)m2<-coxph(Surv(Tstart, Tstop, delta)~type+ttype2, data=kid.long)m3<-coxph(Surv(Tstart, Tstop, delta)~type+ttype3, data=kid.long)m4<-coxph(Surv(Tstart, Tstop, delta)~type+ttype4, data=kid.long)
Results: Kidney> m1
coef exp(coef) se(coef) z ptype 1.44 4.21 1.029 1.40 0.160ttype1 -1.47 0.23 0.587 -2.51 0.012
> m2coef exp(coef) se(coef) z p
type 0.961 2.614 0.751 1.28 0.200ttype2 -0.256 0.774 0.117 -2.18 0.029
> m3coef exp(coef) se(coef) z p
type 0.35 1.4193 0.549 0.637 0.520ttype3 -2.89 0.0555 1.184 -2.443 0.015
> m4coef exp(coef) se(coef) z p
type 0.241 1.272 0.5317 0.453 0.650ttype4 -0.185 0.831 0.0875 -2.113 0.035
BMT Regression Check: FAB### BMT Example (are hazards FAB classes proportional?)bps<-sort(unique(c(bmt$DFS)))bmt.long<-expand.breakpoints(bmt, index="id", status="Either", tevent="DFS", breakpoints=bps)
#create time-dependent covariatesbmt.long$txfab1<-log(bmt.long$Tstop)*(bmt.long$FAB)bmt.long$txfab2<-bmt.long$Tstop*(bmt.long$FAB)bmt.long$txfab3<-ifelse(bmt.long$Tstop>100, (bmt.long$FAB), 0)bmt.long$txfab4<-ifelse(bmt.long$Tstop>100, bmt.long$Tstop*(bmt.long$FAB), 0)
m1<-coxph(Surv(Tstart, Tstop, Either)~FAB+txfab1, data=bmt.long)m2<-coxph(Surv(Tstart, Tstop, Either)~FAB+txfab2, data=bmt.long)m3<-coxph(Surv(Tstart, Tstop, Either)~FAB+txfab3, data=bmt.long)m4<-coxph(Surv(Tstart, Tstop, Either)~FAB+txfab4, data=bmt.long)
Results: FAB> m1
coef exp(coef) se(coef) z pFAB 0.0253 1.03 0.956 0.0264 0.98txfab1 0.1202 1.13 0.182 0.6605 0.51 > m2
coef exp(coef) se(coef) z pFAB 0.541241 1.72 0.299949 1.804 0.071txfab2 0.000341 1.00 0.000706 0.483 0.630 > m3
coef exp(coef) se(coef) z pFAB 0.782 2.185 0.408 1.914 0.056txfab3 -0.206 0.814 0.488 -0.421 0.670 > m4
coef exp(coef) se(coef) z pFAB 0.564772 1.76 0.287651 1.963 0.05txfab4 0.000274 1.00 0.000681 0.403 0.69
BMT Regression Check: MTX#create time-dependent covariates for MTXbmt.long$txmtx1<-log(bmt.long$Tstop)*(bmt.long$MTX)bmt.long$txmtx2<-bmt.long$Tstop*(bmt.long$MTX)bmt.long$txmtx3<-ifelse(bmt.long$Tstop>400, (bmt.long$MTX), 0)bmt.long$txmtx4<-ifelse(bmt.long$Tstop>400, bmt.long$Tstop*(bmt.long$MTX), 0)
m1<-coxph(Surv(Tstart, Tstop, Either)~MTX+txmtx1, data=bmt.long)m2<-coxph(Surv(Tstart, Tstop, Either)~MTX+txmtx2, data=bmt.long)m3<-coxph(Surv(Tstart, Tstop, Either)~MTX+txmtx3, data=bmt.long)m4<-coxph(Surv(Tstart, Tstop, Either)~MTX+txmtx4, data=bmt.long)
Results: MTX> m1
coef exp(coef) se(coef) z pMTX 2.682 14.614 1.124 2.39 0.017txmtx1 -0.459 0.632 0.222 -2.07 0.038
> m2 coef exp(coef) se(coef) z p
MTX 1.22592 3.407 0.38088 3.22 0.0013txmtx2 -0.00377 0.996 0.00154 -2.45 0.0140
> m3 coef exp(coef) se(coef) z p
MTX 0.71 2.033 0.263 2.70 0.0069txmtx3 -1.73 0.178 0.789 -2.19 0.0290
> m4 coef exp(coef) se(coef) z p
MTX 0.70796 2.030 0.26188 2.70 0.0069txmtx4 -0.00303 0.997 0.00143 -2.12 0.0340
Checking Model with >1 Covariate?### Model where MTX is not time-varying> m5a<-coxph(Surv(Tstart, Tstop, Either)~factor(Disease) + FAB + PtAge + DonAge + PtAge*DonAge+MTX, data=bmt.long)> m5aCall:coxph(formula = Surv(Tstart, Tstop, Either) ~ factor(Disease) + FAB + PtAge + DonAge + PtAge * DonAge + MTX, data = bmt.long)
coef exp(coef) se(coef) z pfactor(Disease)2 -1.00606 0.366 0.362370 -2.776 0.00550factor(Disease)3 -0.35406 0.702 0.370966 -0.954 0.34000FAB 0.84303 2.323 0.279461 3.017 0.00260PtAge -0.08522 0.918 0.035708 -2.387 0.01700DonAge -0.08390 0.920 0.030318 -2.767 0.00570MTX 0.30342 1.354 0.252929 1.200 0.23000PtAge:DonAge 0.00315 1.003 0.000943 3.337 0.00085
Likelihood ratio test=34.2 on 7 df, p=1.58e-05 n= 8665, number of events= 83
Checking Model with >1 Covariate?### Model where MTX is not time-varying> m5<-coxph(Surv(Tstart, Tstop, Either)~factor(Disease) + FAB + PtAge + DonAge + PtAge*DonAge+MTX+txmtx1, data=bmt.long)> m5Call: coxph(formula = Surv(Tstart, Tstop, Either) ~ factor(Disease) + FAB + PtAge + DonAge + PtAge * DonAge + MTX + txmtx1, data = bmt.long)
coef exp(coef) se(coef) z pfactor(Disease)2 -1.01485 0.362 0.362198 -2.802 0.0051factor(Disease)3 -0.32998 0.719 0.368393 -0.896 0.3700FAB 0.88170 2.415 0.278466 3.166 0.0015PtAge -0.08201 0.921 0.035909 -2.284 0.0220DonAge -0.08490 0.919 0.030965 -2.742 0.0061MTX 2.69860 14.859 1.152782 2.341 0.0190txmtx1 -0.47772 0.620 0.225152 -2.122 0.0340PtAge:DonAge 0.00305 1.003 0.000955 3.194 0.0014
Likelihood ratio test=39.5 on 8 df, p=3.93e-06 n= 8665, number of events= 83
Alternative Form of Time-Varying Covariate
• So far we’ve guessed at g(t)• Problem is we don’t necessarily know the
correct functional form• Consider a binary covariate, Z1
• Assume for covariate Z1, the relative risk changes over time
• What if we use the data instead– Get “best estimate” from the data
Change Point Model• Let
• This gives us proportional hazards model with a change point at t(Liang et. Al (1990))
• Fit proportional hazards model with Z1 and Z2(t)
• We now have a PH model with HR:
– Model: H(t|Z (t)) = h0(t)exp{b1Z1 + b2Z2 }
– h(t|Z(t)) = h0(t)exp{b1Z1} if t < t
– h(t|Z(t)) = h0(t)exp{(b1 + b2)Z1} if t > t
• So we are fitting a PH model that includes a change point, which allows the HR to change after a specified time
12 0
Z if tZ t
if t
How to Determine t
• A change point for the relative risk was introduced. Where is the best change point?
• Recall the partial likelihood only changes at event times
• Calculate log likelihood at each event time where t represents specific event times
• Choose t that yields the largest log-likelihood
Kidney Example#Change point model >cps<-sort(unique(kidney$time[which(kidney$delta==1)]))>LL<-c()>for (i in 1:length(cps))>{> z2<-ifelse(kid.long$Tstop>cps[i], kid.long$type, 0)> mod<-coxph(Surv(Tstart, Tstop, delta)~type+z2, data=kid.long, > method="breslow")> LL<-append(LL, mod$loglik[2])>}
> round(LL, digits=3) [1] -97.878 -100.224 -97.630 -97.501 -99.683 -100.493 -98.856 -100.428 [9] -101.084 -101.668 -102.168 -100.829 -101.477 -102.059 -102.620 -103.229
Change Point ResultsEvent Times Log Partial Likelihood
0.5 -97.8781.5 -100.2242.5 -97.6303.5 -97.5014.5 -99.6835.5 -100.4936.5 -98.8568.5 -100.4289.5 -101.084
10.5 -101.66811.5 -102.16815.5 -100.82916.5 -101.47718.5 -102.05923.5 -102.620
What About Multiple Comparisons?
• Is it “fishing” to try many cutpoints?• No, we are conducting diagnostics so we don’t
worry so much• We aren’t sure of the form of a time-
dependence so we are being flexible to identify if we are missing something
Hazards Not Proportional• Proportional hazards assumption doesn’t
hold… what can we do?• Single binary covariate… consider a piecewise
regression– Change-point identified by data (alternate coding)
• Many covariates, consider stratified model on non-proportional covariate
1 12 3
if if
0 if 0 if
Z t Z tZ t Z t
t t
Kidney: 1-Covariate with Change-Point
> kid.long$z2<-ifelse(kid.long$Tstop>3.5, kid.long$cath, 0)> kid.long$z3<-ifelse(kid.long$Tstop<=3.5, kid.long$cath, 0)> mod<-coxph(Surv(Tstart, Tstop, d)~z2+z3, data=kid.long, method="breslow") > modCall:coxph(formula = Surv(Tstart, Tstop, d) ~ z2 + z3, data = kid.long, method = "breslow")
coef exp(coef) se(coef) z p z2 -2.09 0.124 0.760 -2.75 0.006z3 1.08 2.950 0.783 1.38 0.170
Likelihood ratio test=13.9 on 2 df, p=0.000956 n= 1132, number of events= 26
Interpretation?
• Up to 3.5 months, there is a there is not a significant difference in risk of infection between the two groups.
• However, after 3.5 months the relative risk of infection in patients with percutaneously placed catheters is 0.12 times the risk relative to patients with surgically placed catheters.
• Recall our hazard rate plots– Hazards crossed at about 3.5 months
A Few Points
• A single cutpoint may not be enough– There are “two” models– Within in each piece, we are still assuming
proportional hazards• Check proportional hazards models within
each of the time intervals• Can generate additional time varying
covariates within each interval
Stratified Cox Regression
• Recall stratification• Estimates ‘pooled’ association across strata• Stratification in regression– Estimates pooled regression coefficient– Strong assumption that associations between
covariate and outcome are the same across strata
Estimation: Partial Likelihood Approach
• Partition dataset based on strata• Define log-likelihood per strata• Log-likelihood based on J strata
• Maximize LL(b) w.r.t. b• Notice b is common across all the strata specific
partial log-likelihoods
'0
1 2
exp , 1,2,...,
...
j j
J
h t t h t t j J
LL LL LL LL
Z Z
BMT: Stratified Model
• Steps:1) Check proportional hazards assumption2) Fit stratified cox model3) Check model assumptions (i.e. constant b’s… more on this in a moment)
• We’ve already seen that the proportional hazards assumption for Methotrexate use is incorrect.
BMT Data• Associations between covariates and DFS, stratified by diagnosis
> reg2a<-coxph(Surv(Tstart, Tstop, Either)~ factor(Disease)+ FAB+DonAge:PtAge+TRP+strata(MTX), data = bmt.long2)> reg2aCall:coxph(formula=Surv(Tstart, Tstop,Either)~factor(Disease)+FAB+DonAge+
PtAge+DonAge*PtAge+PRt+strata(MTX), data = bmt.long2)
coef exp(coef) se(coef) z pfactor(Disease)2 -1.00911 0.365 0.364333 -2.770 0.0056factor(Disease)3 -0.34552 0.708 0.370254 -0.933 0.3500FAB 0.89008 2.435 0.280684 3.171 0.0015DonAge -0.08415 0.919 0.031123 -2.704 0.0069PtAge -0.08175 0.921 0.036255 -2.255 0.0240PRt 2.08909 8.078 1.095274 1.907 0.0560DonAge:PtAge 0.00301 1.003 0.000957 3.143 0.0017
Likelihood ratio test=33.4 on 7 df, p=2.23e-05 n= 19070, number of events= 83
Is Assumption of Constant b Reasonable?
• Testing assumption• Divide dataset into J strata• Fit model with p covariates in each strata• Define• Define based on stratified model• Test significance via LRT
1 21...
J
j j j J jjLL LL LL LL
b b b b
LL b
2 2
112
J
LRT j j J pjX LL LL
b b
Checking Constant b Assumption#Testing stratification assumptionreg2a<-coxph(Surv(Tstart, Tstop, Either) ~ factor(Disease) + FAB + DonAge + PtAge + DonAge*PtAge +PRt + strata(MTX), data=bmt.long2)
dat1<-bmt.long2[bmt.long2$MTX==0,]reg2b<-coxph(Surv(Tstart, Tstop, Either) ~ factor(Disease) + FAB + DonAge + PtAge + DonAge*PtAge +PRt + strata(MTX), data=dat1)
dat2<-bmt.long2[bmt.long2$MTX==1,]reg2c<-coxph(Surv(Tstart, Tstop, Either) ~ factor(Disease) + FAB + DonAge + PtAge + DonAge*PtAge +PRt + strata(MTX), data=dat2)
LL2<-reg2$loglik[2]LL3<-reg3a$loglik[2]+reg3b$loglik[2]+reg3c$loglik[2]lrt<-2*(LL3-LL2)p.lrt<-1-pchisq(lrt, 2)
> reg2b coef exp(coef) se(coef) z p
factor(Disease)2 -1.19655 0.302 0.4585 -2.610 0.0091factor(Disease)3 -0.29025 0.748 0.4451 -0.652 0.5100FAB 1.08896 2.971 0.3384 3.218 0.0013DonAge -0.08378 0.920 0.0371 -2.258 0.0240PtAge -0.03630 0.964 0.0536 -0.677 0.5000PRt -0.86747 0.420 0.4793 -1.810 0.0700DonAge:PtAge 0.00227 1.002 0.0014 1.618 0.1100
> reg2c coef exp(coef) se(coef) z p
factor(Disease)2 -0.56372 0.569 0.63847 -0.8829 0.380factor(Disease)3 -0.85828 0.424 0.91761 -0.9353 0.350FAB 0.34408 1.411 0.65122 0.5284 0.600DonAge -0.00452 0.995 0.08152 -0.0555 0.960PtAge -0.02724 0.973 0.08073 -0.3374 0.740PRt -1.00688 0.365 0.55118 -1.8268 0.068DonAge:PtAge 0.00138 1.001 0.00227 0.6098 0.540
Results> LL.piece<-reg2b$loglik[2]+reg2c$loglik[2]> LL.strat<-reg2a$loglik[2]
> lrt<-2*(LL.piece-LL.strat)> lrt[1] 6.118211
> p.lrt<-1-pchisq(lrt, 7)> p.lrt[1] 0.5260164
Next Time
• Regression diagnostics using residuals!