*! version 1.2.2 27jul2009 /* *! with PR mods 14apr2008 & 09mar2009, indicated by !! PR. *! 12March2009 - changed to using Newton-Raphson method for estimating centiles. *! 11March2009 - fixed problem with strings>244 characters for long varlists. *! Added sdiff1 and sdiff2 options for difference in survival curves. *! Added hdiff1 and hdiff2 options for difference in survival curves. *! 23/8/2008 Fixed bug for some predictions involving time-dependent effects. *! 11/12/2008 Changed to using rcsgen for spline functions. */ program stpm2_pred version 10.0 syntax newvarname [if] [in], [Survival Hazard XB XBNOBaseline DXB DZDY HRNumerator(string) HRDenominator(string) MEANSurv /// CENtile(string) CUMHazard CUMOdds NORmal MARTingale DEViance DENSity AT(string) ZEROs /// noOFFset SDIFF1(string) SDIFF2(string) HDIFF1(string) HDIFF2(string) /// CI LEVel(real `c(level)') TIMEvar(varname) STDP PER(real 1) /// CENTOL(real 0.0001)] marksample touse, novarlist local newvarname `varlist' qui count if `touse' if r(N)==0 { error 2000 /* no observations */ } /* Check Options */ if "`hrdenominator'" != "" & "`hrnumerator'" == "" { display as error "You must specifiy the hrnumerator option if you specifiy the hrdenominator option" exit 198 } if "`sdiff2'" != "" & "`sdiff1'" == "" { display as error "You must specifiy the sdiff1 option if you specifiy the sdiff2 option" exit 198 } if "`hdiff2'" != "" & "`hdiff1'" == "" { display as error "You must specifiy the hdiff1 option if you specifiy the hdiff2 option" exit 198 } local hratiotmp = substr("`hrnumerator'",1,1) local sdifftmp = substr("`sdiff1'",1,1) local hdifftmp = substr("`hdiff1'",1,1) if wordcount(`"`survival' `hazard' `meansurv' `hratiotmp' `sdifftmp' `hdifftmp' `centile' `xb' `xbnobaseline' `dxb' `dzdy' `martingale' `deviance' `cumhazard' `cumodds' `normal' `density'"') > 1 { display as error "You have specified more than one option for predict" exit 198 } if wordcount(`"`survival' `hazard' `meansurv' `hrnumerator' `sdiff1' `hdifftmp' `centile' `xb' `xbnobaseline' `dxb' `dzdy' `martingale' `deviance' `cumhazard' `cumodds' `normal' `density'"') == 0 { display as error "You must specify one of the predict options" exit 198 } if `per' != 1 & "`hazard'" == "" & "`hdiff1'" == "" { display as error "You can only use the per() option in combinaton with the hazard or hdiff1()/hdiff2() options." exit 198 } if "`stdp'" != "" & "`ci'" != "" { display as error "You can not specify both the ci and stdp options." exit 19 } if "`stdp'" != "" & /// wordcount(`"`xb' `dxb' `xbnobaseline'"') == 0 { display as error "The stdp option can only be used with the xb, dxb and xbnobaseline prediction options." exit 198 } if "`ci'" != "" & /// wordcount(`"`survival' `hazard' `hrnumerator' `sdiff1' `hdiff1' `centile' `xb' `dxb' `xbnobaseline'"') == 0 { display as error "The ci option can not be used with this predict option." exit 198 } if "`zeros'" != "" & "`meansurv'" != "" { display as error "You can not specify the zero option with the meansurv option." exit 198 } if "`zeros'" != "" & ("`hrnumerator'" != "" | "`hdiff1'" != "" | "`sdiff1'" != "") { display as error "You can not specify the zero option with the hrnumerator, hdiff or sdiff options." exit 198 } if "`at'" != "" & "`hrnumerator'" != "" { display as error "You can not use the at option with the hrnumerator option" exit 198 } if "`at'" != "" & "`sdiff1'" != "" { display as error "You can not use the at option with the sdiff1 and sdiff2 options" exit 198 } if "`at'" != "" & "`hdiff1'" != "" { display as error "You can not use the at option with the hdiff1 and hdiff2 options" exit 198 } if "`meansurv'" != "" & ("`ci'" != "") { display as error "You can not use the ci option with the meansurv option" exit 198 } /* call stmeancurve if meansurv option specified */ if "`meansurv'" != "" { Stmeancurve `newvarname' if `touse', timevar(`timevar') at(`at') `offset' exit } /* calculate midt for centile option */ summ _t, meanonly local midt = (r(max) - r(min))/2 /* store time-dependent covariates */ local etvc `e(tvc)' /* dydx option of old version of stpm */ if "`dzdy'" != "" { local dxb dxb } /* generate ocons for use when orthogonalising splines */ tempvar ocons gen `ocons' = 1 /* Use _t if option timevar not specified */ tempvar t lnt if "`timevar'" == "" { qui gen double `t' = _t if `touse' qui gen double `lnt' = ln(_t) if `touse' } else { qui gen double `t' = `timevar' if `touse' qui gen double `lnt' = ln(`timevar') if `touse' } /* Check to see if nonconstant option used */ if "`e(noconstant)'" == "" { tempvar cons qui gen `cons' = 1 if `touse' } /* Preserve data for out of sample prediction */ tempfile newvars tempname merge preserve /* Calculate new spline terms if timevar option specified */ if "`timevar'" != "" { capture drop _rcs* _d_rcs* qui rcsgen `lnt' if `touse', knots(`e(ln_bhknots)') gen(_rcs) dgen(_d_rcs) if "`e(orthog)'" != "" { mata st_store(.,tokens(st_global("e(rcsterms_base)")),"`touse'",(st_data(.,(tokens(st_global("e(rcsterms_base)") + " `ocons'" )),"`touse'")*luinv(st_matrix("e(R_bh)")))[,1..`e(dfbase)']) mata st_store(.,tokens(st_global("e(drcsterms_base)")),"`touse'",(st_data(.,(tokens(st_global("e(drcsterms_base)"))),"`touse'")*luinv(st_matrix("e(R_bh)"))[1..`e(dfbase)',1..`e(dfbase)'])[,1..`e(dfbase)']) } } /* calculate new spline terms if timevar option or hrnumerator option is specified */ if "`timevar'" != "" | "`hrnumerator'" != "" | "`sdiff1'" != "" | "`hdiff1'" != "" { foreach tvcvar in `e(tvc)' { if ("`hrnumerator'" != "" | "`sdiff1'" != "" | "`hdiff1'" != "") & "`timevar'" == ""{ capture drop _rcs_`tvcvar'* _d_rcs_`tvcvar'* } qui rcsgen `lnt' if `touse', gen(_rcs_`tvcvar') knots(`e(ln_tvcknots_`tvcvar')') dgen(_d_rcs_`tvcvar') if "`e(orthog)'" != "" { mata st_store(.,tokens(st_global("e(rcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(rcsterms_`tvcvar')") + " `ocons'" )),"`touse'")*luinv(st_matrix("e(R_`tvcvar')")))[,1..`e(df_`tvcvar')']) mata st_store(.,tokens(st_global("e(drcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(drcsterms_`tvcvar')"))),"`touse'")*luinv(st_matrix("e(R_`tvcvar')"))[1..`e(df_`tvcvar')',1..`e(df_`tvcvar')'])[,1..`e(df_`tvcvar')']) } if "`hrnumerator'" == "" & "`sdiff1'" == "" & "`hdiff1'" == "" { forvalues i = 1/`e(df_`tvcvar')'{ qui replace _rcs_`tvcvar'`i' = _rcs_`tvcvar'`i'*`tvcvar' if `touse' qui replace _d_rcs_`tvcvar'`i' = _d_rcs_`tvcvar'`i'*`tvcvar' if `touse' } } } } /* zeros */ if "`zeros'" != "" { foreach var in `e(varlist)' { if `"`: list posof `"`var'"' in at'"' == "0" { qui replace `var' = 0 if `touse' foreach tvcvar in `e(tvc)' { forvalues i = 1/`e(df_`tvcvar')' { qui replace _rcs_`tvcvar'`i' = 0 if `touse' qui replace _d_rcs_`tvcvar'`i' = 0 if `touse' } } } } } /* Out of sample predictions using at() */ if "`at'" != "" { tokenize `at' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { cap confirm num `2' if _rc { di in red "invalid at(... `1' `2' ...)" exit 198 } } qui replace `1' = `2' if `touse' if `"`: list posof `"`1'"' in etvc'"' != "0" { local tvcvar `1' capture drop _rcs_`tvcvar'* _d_rcs_`tvcvar'* qui rcsgen `lnt' if `touse', knots(`e(ln_tvcknots_`tvcvar')') gen(_rcs_`tvcvar') dgen(_d_rcs_`tvcvar') if "`e(orthog)'" != "" { mata st_store(.,tokens(st_global("e(rcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(rcsterms_`tvcvar')") + " `ocons'" )),"`touse'")*luinv(st_matrix("e(R_`tvcvar')")))[,1..`e(df_`tvcvar')']) mata st_store(.,tokens(st_global("e(drcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(drcsterms_`tvcvar')"))),"`touse'")*luinv(st_matrix("e(R_`tvcvar')"))[1..`e(df_`tvcvar')',1..`e(df_`tvcvar')'])[,1..`e(df_`tvcvar')']) } forvalues i = 1/`e(df_`tvcvar')'{ qui replace _rcs_`tvcvar'`i' = _rcs_`tvcvar'`i'*`tvcvar' if `touse' qui replace _d_rcs_`tvcvar'`i' = _d_rcs_`tvcvar'`i'*`tvcvar' if `touse' } } mac shift 2 } } /* Add offset term if exists unless no offset option is specified */ if "`e(offset1)'" != "" & /* !! PR */ "`offset'" != "nooffset" { local addoff "+ `e(offset1)'" } /* check ci and stdp options */ if "`ci'" != "" & "`stdp'" != "" { display as error "Only one of the ci and se options can be specified" exit 198 } /* Deviance and Martingale Residuals */ if "`deviance'" != "" | "`martingale'" != "" { tempvar cH res qui predict `cH' if `touse', cumhazard timevar(`t') /* !! pr */ `offset' gen double `res' = _d - `cH' if `touse' if "`deviance'" != "" { gen double `newvarname' = sign(`res')*sqrt( -2*(`res' + _d*(ln(_d -`res')))) if `touse' } else rename `res' `newvarname' } /* Cumulative Hazard */ else if "`cumhazard'" != "" { tempvar S predict `S' if `touse', s timevar(`t') /* !! pr */ `offset' gen `newvarname' = -ln(`S') if `touse' } /* Cumulative Odds */ else if "`cumodds'" != "" { tempvar S predict `S' if `touse', s timevar(`t') /* !! pr */ `offset' gen `newvarname' = (1 -`S')/`S' if `touse' } /* Standard Normal Deviate */ else if "`normal'" != "" { tempvar S predict `S' if `touse', s timevar(`t') /* !! pr */ `offset' gen `newvarname' = -invnormal(`S') if `touse' } /* density */ else if "`density'" != "" { tempvar S h predict `S' if `touse', s timevar(`t') /* !! pr */ `offset' predict `h' if `touse', h timevar(`t') /* !! pr */ `offset' gen `newvarname' = `S'*`h' if `touse' } /* linear predictor */ else if "`xb'" != "" { if "`ci'" != "" { local prednlopt ci(`newvarname'_lci `newvarname'_uci) } else if "`stdp'" != "" { local prednlopt se(`newvarname'_se) } qui predictnl double `newvarname' = xb(xb) `addoff' if `touse', `prednlopt' level(`level') } /* derivative of linear predictor */ else if "`dxb'" != "" { if "`ci'" != "" { local prednlopt ci(`newvarname'_lci `newvarname'_uci) } else if "`stdp'" != "" { local prednlopt se(`newvarname'_se) } qui predictnl double `newvarname' = xb(dxb) if `touse', `prednlopt' level(`level') } /* linear predictor exluding spline terms */ else if "`xbnobaseline'" != "" { if "`ci'" != "" { local prednlopt ci(`newvarname'_lci `newvarname'_uci) } else if "`stdp'" != "" { local prednlopt se(`newvarname'_se) } /* commented out for now - ignores the constant (gamma_0) - may be needed later if "`e(noconstant)'" == "" { local xbnobhpred [xb][_cons] } */ // !! PR bug fix next 5 lines foreach var in `e(varlist)' { if "`xbnobhpred'" == "" local xbnobhpred [xb][`var']*`var' else local xbnobhpred `xbnobhpred' + [xb][`var']*`var' if `"`: list posof `"`var'"' in etvc'"' != "0" { forvalues i = 1/`e(df_`var')' { local xbnobhpred `xbnobhpred' + [xb][_rcs_`var'`i']*_rcs_`var'`i' } } } * if "`e(noconstant)'" != "" { * local xbnobhpred = subinstr("`xbnobhpred'","+","",1) * } predictnl double `newvarname' = `xbnobhpred' if `touse', `prednlopt' level(`level') } /* Survival Function */ else if "`survival'" != "" { tempvar sxb if "`ci'" != "" { tempvar sxb_lci sxb_uci local prednlopt ci(`sxb_lci' `sxb_uci') } if "`e(scale)'" != "theta" { qui predictnl double `sxb' = xb(xb) `addoff' if `touse', `prednlopt' level(`level') } /* predict on ln(-ln S(t)) scale for theta */ else if "`e(scale)'" == "theta" { qui predictnl double `sxb' = ln(ln(exp(xb(ln_theta))*exp(xb(xb)`addoff')+1)/exp(xb(ln_theta))) if `touse', `prednlopt' level(`level') } /* Transform back to survival scale */ if "`e(scale)'" == "hazard" { qui gen double `newvarname' = exp(-exp(`sxb')) if `touse' if "`ci'" != "" { qui gen `newvarname'_lci = exp(-exp(`sxb_uci')) if `touse' qui gen `newvarname'_uci = exp(-exp(`sxb_lci')) if `touse' } } else if "`e(scale)'" == "odds" { qui gen double `newvarname' = (1 +exp(`sxb'))^(-1) if `touse' if "`ci'" != "" { qui gen `newvarname'_lci = (1 +exp(`sxb_uci'))^(-1) if `touse' qui gen `newvarname'_uci = (1 +exp(`sxb_lci'))^(-1) if `touse' } } else if "`e(scale)'" == "normal" { qui gen double `newvarname' = normal(-`sxb') if `touse' if "`ci'" != "" { qui gen `newvarname'_lci = normal(-`sxb_uci') if `touse' qui gen `newvarname'_uci = normal(-`sxb_lci') if `touse' } } else if "`e(scale)'" == "theta" { qui gen double `newvarname' = exp(-exp(`sxb')) if `touse' if "`ci'" != "" { qui gen `newvarname'_lci = exp(-exp(`sxb_lci')) if `touse' qui gen `newvarname'_uci = exp(-exp(`sxb_uci')) if `touse' } } } /* Hazard Function */ else if "`hazard'" != "" { tempvar lnh if "`ci'" != "" { tempvar lnh_lci lnh_uci local prednlopt ci(`lnh_lci' `lnh_uci') } if "`e(scale)'" == "hazard" { qui predictnl double `lnh' = -ln(`t') + ln(xb(dxb)) + xb(xb) `addoff' if `touse', `prednlopt' level(`level') } if "`e(scale)'" == "odds" { qui predictnl double `lnh' = -ln(`t') + ln(xb(dxb)) + (xb(xb)`addoff') -ln(1+exp(xb(xb)`addoff')) if `touse', `prednlopt' level(`level') } if "`e(scale)'" == "normal" { qui predictnl double `lnh' = -ln(`t') + ln(xb(dxb)) + ln(normalden(xb(xb)`addoff')) - ln(normal(-(xb(xb)`addoff'))) if `touse', `prednlopt' level(`level') } if "`e(scale)'" == "theta" { qui predictnl double `lnh' = -ln(`t') + ln(xb(dxb)) + xb(`xb') - ln(exp(xb(ln_theta))*exp(xb(xb)`addoff') + 1) if `touse', `prednlopt' level(`level') } /* Transform back to hazard scale */ qui gen double `newvarname' = exp(`lnh')*`per' if `touse' if "`ci'" != "" { qui gen `newvarname'_lci = exp(`lnh_lci')*`per' if `touse' qui gen `newvarname'_uci = exp(`lnh_uci')*`per' if `touse' } } /* Predict Hazard Ratio */ else if "`hrnumerator'" != "" { tempvar lhr lhr_lci lhr_uci if `"`ci'"' != "" { local hazci "ci(`lhr_lci' `lhr_uci')" } forvalues i=1/`e(dfbase)' { local dxb1 `dxb1' [xb][_rcs`i']*_d_rcs`i' local dxb0 `dxb0' [xb][_rcs`i']*_d_rcs`i' local xb1_plus `xb1_plus' [xb][_rcs`i']*_rcs`i' local xb0_plus `xb0_plus' [xb][_rcs`i']*_rcs`i' if `i' != `e(dfbase)' { local dxb0 `dxb0' + local dxb1 `dxb1' + local xb1_plus `xb1_plus' + local xb0_plus `xb0_plus' + } } tokenize `hrnumerator' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { if "`2'" == "." { local 2 `1' } else { cap confirm num `2' if _rc { di in red "invalid hrnumerator(... `1' `2' ...)" exit 198 } } } if "`xb10'" != "" & "`2'" != "0" { local xb10 `xb10' + } if "`xb1_plus'" != "" & "`2'" != "0" { local xb1_plus `xb1_plus' + } if "`2'" != "0" { local xb10 `xb10' [xb][`1']*`2' local xb1_plus `xb1_plus' [xb][`1']*`2' } if `"`: list posof `"`1'"' in etvc'"' != "0" & "`2'" != "0" { local dxb1 `dxb1' + local xb10 `xb10' + local xb1_plus `xb1_plus' + forvalues i=1/`e(df_`1')' { local dxb1 `dxb1' [xb][_rcs_`1'`i']*_d_rcs_`1'`i'*`2' local xb10 `xb10' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' local xb1_plus `xb1_plus' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' if `i' != `e(df_`1')' { local dxb1 `dxb1' + local xb10 `xb10' + local xb1_plus `xb1_plus' + } } } mac shift 2 } if "`hrdenominator'" != "" { tokenize `hrdenominator' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { if "`2'" == "." { local 2 `1' } else { cap confirm num `2' if _rc { di in red "invalid denominator(... `1' `2' ...)" exit 198 } } } if "`2'" != "0" { local xb10 `xb10' - [xb][`1']*`2' local xb0_plus `xb0_plus' + [xb][`1']*`2' } if `"`: list posof `"`1'"' in etvc'"' != "0" & "`2'" != "0" { local dxb0 `dxb0' + local xb10 `xb10' - local xb0_plus `xb0_plus' + forvalues i=1/`e(df_`1')' { local dxb0 `dxb0' [xb][_rcs_`1'`i']*_d_rcs_`1'`i'*`2' local xb10 `xb10' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' local xb0_plus `xb0_plus' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' if `i' != `e(df_`1')' { local dxb0 `dxb0' + local xb10 `xb10' - local xb0_plus `xb0_plus' + } } } mac shift 2 } } if "`e(noconstant)'" == "" { local xb0_plus `xb0_plus' + [xb][_cons] local xb1_plus `xb1_plus' + [xb][_cons] } if "`e(scale)'" =="hazard" { qui predictnl double `lhr' = ln(`dxb1') - ln(`dxb0') + `xb10' if `touse', `hazci' level(`level') } else if "`e(scale)'" =="odds" { qui predictnl double `lhr' = ln(`dxb1') - ln(`dxb0') + `xb10' - /// ln(1+exp(`xb1_plus')) + ln(1+exp(`xb0_plus')) /// if `touse', `hazci' level(`level') } else if "`e(scale)'" =="normal" { qui predictnl double `lhr' = ln(`dxb1') - ln(`dxb0') + /// ln(normalden(`xb1_plus')) - ln(normalden(`xb0_plus')) - /// ln(normal(-(`xb1_plus'))) + ln(normal(-(`xb0_plus'))) /// if `touse', `hazci' level(`level') } else if "`e(scale)'" =="theta" { qui predictnl double `lhr' = ln(`dxb1') - ln(`dxb0') + `xb10' /// -ln(exp(xb(ln_theta))*exp(`xb1_plus') + 1) + ln(exp(xb(ln_theta))*exp(`xb0_plus') + 1) /// if `touse', `hazci' level(`level') } qui gen double `newvarname' = exp(`lhr') if `touse' if `"`ci'"' != "" { qui gen double `newvarname'_lci=exp(`lhr_lci') if `touse' qui gen double `newvarname'_uci=exp(`lhr_uci') if `touse' } } /* Predict Difference in Hazard Functions */ else if "`hdiff1'" != "" { if `"`ci'"' != "" { local hazci "ci(`newvarname'_lci `newvarname'_uci)" } forvalues i=1/`e(dfbase)' { local dxb1 `dxb1' [xb][_rcs`i']*_d_rcs`i' local dxb0 `dxb0' [xb][_rcs`i']*_d_rcs`i' local xb1_plus `xb1_plus' [xb][_rcs`i']*_rcs`i' local xb0_plus `xb0_plus' [xb][_rcs`i']*_rcs`i' if `i' != `e(dfbase)' { local dxb0 `dxb0' + local dxb1 `dxb1' + local xb1_plus `xb1_plus' + local xb0_plus `xb0_plus' + } } tokenize `hdiff1' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { if "`2'" == "." { local 2 `1' } else { cap confirm num `2' if _rc { di in red "invalid hdiff1(... `1' `2' ...)" exit 198 } } } if "`xb1_plus'" != "" & "`2'" != "0" { local xb1_plus `xb1_plus' + } if "`2'" != "0" { local xb1_plus `xb1_plus' [xb][`1']*`2' } if `"`: list posof `"`1'"' in etvc'"' != "0" & "`2'" != "0" { local dxb1 `dxb1' + local xb10 `xb10' + local xb1_plus `xb1_plus' + forvalues i=1/`e(df_`1')' { local dxb1 `dxb1' [xb][_rcs_`1'`i']*_d_rcs_`1'`i'*`2' local xb1_plus `xb1_plus' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' if `i' != `e(df_`1')' { local dxb1 `dxb1' + local xb1_plus `xb1_plus' + } } } mac shift 2 } if "`hdiff2'" != "" { tokenize `hdiff2' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { if "`2'" == "." { local 2 `1' } else { cap confirm num `2' if _rc { di in red "invalid hdiff2(... `1' `2' ...)" exit 198 } } } if "`2'" != "0" { local xb0_plus `xb0_plus' + [xb][`1']*`2' } if `"`: list posof `"`1'"' in etvc'"' != "0" & "`2'" != "0" { local dxb0 `dxb0' + local xb0_plus `xb0_plus' + forvalues i=1/`e(df_`1')' { local dxb0 `dxb0' [xb][_rcs_`1'`i']*_d_rcs_`1'`i'*`2' local xb0_plus `xb0_plus' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' if `i' != `e(df_`1')' { local dxb0 `dxb0' + local xb0_plus `xb0_plus' + } } } mac shift 2 } } if "`e(noconstant)'" == "" { local xb0_plus `xb0_plus' + [xb][_cons] local xb1_plus `xb1_plus' + [xb][_cons] } if "`e(scale)'" =="hazard" { qui predictnl double `newvarname' = (1/`t' * (`dxb1')*exp(`xb1_plus') - 1/`t' * (`dxb0')*exp(`xb0_plus'))*`per' /// if `touse', `hazci' level(`level') } else if "`e(scale)'" =="odds" { qui predictnl double `newvarname' = (1/`t' *(`dxb1')*exp(`xb1_plus')/((1 + exp(`xb1_plus'))) - /// 1/`t' *(`dxb0')*exp(`xb0_plus')/((1 + exp(`xb0_plus'))))*`per' /// if `touse', `hazci' level(`level') } else if "`e(scale)'" =="normal" { qui predictnl double `newvarname' = (1/`t' *(`dxb1')*normalden(`xb1_plus')/normal(-(`xb1_plus')) - /// 1/`t' *(`dxb0')*normalden(`xb0_plus')/normal(-(`xb0_plus')))*`per' /// if `touse', `hazci' level(`level') } else if "`e(scale)'" =="theta" { qui predictnl double `newvarname' = (1/`t' *((`dxb1')*exp(`xb1_plus'))/((exp([ln_theta][_cons])*exp(`xb1_plus') + 1)) - /// 1/`t' *((`dxb0')*exp(`xb0_plus'))/((exp([ln_theta][_cons])*exp(`xb0_plus') + 1)))*`per' if `touse', `hazci' level(`level') } } /* Predict Difference in Survival Curves */ else if "`sdiff1'" != "" { if `"`ci'"' != "" { local survdiffci "ci(`newvarname'_lci `newvarname'_uci)" } forvalues i=1/`e(dfbase)' { local xb1_plus `xb1_plus' [xb][_rcs`i']*_rcs`i' local xb0_plus `xb0_plus' [xb][_rcs`i']*_rcs`i' if `i' != `e(dfbase)' { local xb1_plus `xb1_plus' + local xb0_plus `xb0_plus' + } } tokenize `sdiff1' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { if "`2'" == "." { local 2 `1' } else { cap confirm num `2' if _rc { di in red "invalid sdiff1(... `1' `2' ...)" exit 198 } } } if "`xb1_plus'" != "" & "`2'" != "0" { local xb1_plus `xb1_plus' + } if "`2'" != "0" { local xb1_plus `xb1_plus' [xb][`1']*`2' } if `"`: list posof `"`1'"' in etvc'"' != "0" & "`2'" != "0" { local xb1_plus `xb1_plus' + forvalues i=1/`e(df_`1')' { local xb1_plus `xb1_plus' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' if `i' != `e(df_`1')' { local xb1_plus `xb1_plus' + } } } mac shift 2 } if "`sdiff2'" != "" { tokenize `sdiff2' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { if "`2'" == "." { local 2 `1' } else { cap confirm num `2' if _rc { di in red "invalid sdiff2(... `1' `2' ...)" exit 198 } } } if "`2'" != "0" { local xb0_plus `xb0_plus' + [xb][`1']*`2' } if `"`: list posof `"`1'"' in etvc'"' != "0" & "`2'" != "0" { local xb0_plus `xb0_plus' + forvalues i=1/`e(df_`1')' { local xb0_plus `xb0_plus' [xb][_rcs_`1'`i']*_rcs_`1'`i'*`2' if `i' != `e(df_`1')' { local xb0_plus `xb0_plus' + } } } mac shift 2 } } if "`e(noconstant)'" == "" { local xb0_plus `xb0_plus' + [xb][_cons] local xb1_plus `xb1_plus' + [xb][_cons] } if "`e(scale)'" =="hazard" { qui predictnl double `newvarname' = exp(-exp(`xb1_plus')) - exp(-exp(`xb0_plus')) if `touse', `survdiffci' level(`level') } else if "`e(scale)'" =="odds" { qui predictnl double `newvarname' = 1/(exp(`xb1_plus')+1) - 1/(exp(`xb0_plus')+1) if `touse', `survdiffci' level(`level') } else if "`e(scale)'" =="normal" { qui predictnl double `newvarname' = normal(-(`xb1_plus')) - normal(-(`xb0_plus')) if `touse', `survdiffci' level(`level') } else if "`e(scale)'" =="theta" { qui predictnl double `newvarname' = (exp([ln_theta][_cons])*exp(`xb1_plus') + 1)^(-1/exp([ln_theta][_cons])) /// -(exp([ln_theta][_cons])*exp(`xb0_plus') + 1)^(-1/exp([ln_theta][_cons])) /// if `touse', `hazci' level(`level') } } /* Predicted survival time for a given centile */ /* Estimated using Newton-Raphson alogorithm (updated from ridder method in version 1.2.2) */ else if "`centile'" != "" { /* transform to appropriate scale */ tempvar transcent centilevar gen `centilevar' = 1 - `centile'/100 if `touse' if "`e(scale)'" == "hazard" { qui gen double `transcent' = ln(-ln(`centilevar')) if `touse' } else if "`e(scale)'" == "odds" { qui gen double `transcent' = ln(1/`centilevar'-1) if `touse' } else if "`e(scale)'" == "normal" { qui gen double `transcent' = -invnorm(`centilevar') if `touse' } else if "`e(scale)'" == "theta" { qui gen double `transcent' = ln((`centilevar'^(-exp([ln_theta][_cons]))-1)/exp([ln_theta][_cons])) if `touse' } /* initial values */ tempvar tmpxb nr_time nr_time_old nr_xb nr_dxb maxerr qui gen double `nr_time' = `midt' qui gen double `nr_time_old' = `nr_time' if `touse' /* loop */ local done 0 while !`done' { qui predict `nr_xb' if `touse', xb timevar(`nr_time_old') `offset' qui predict `nr_dxb' if `touse', dxb timevar(`nr_time_old') qui replace `nr_time' = exp(ln(`nr_time_old') - (`nr_xb' - `transcent')/`nr_dxb') if `touse' qui gen double `maxerr' = abs(`nr_time' - `nr_time_old') if `touse' summ `maxerr' if `touse', meanonly if r(max)<`centol' { local done 1 } else { drop `nr_xb' `nr_dxb' `maxerr' qui replace `nr_time_old' = `nr_time' if `touse' } } qui gen double `newvarname' = `nr_time' if `touse' if "`ci'" != "" { tempvar lnln_s lnln_s_se h tp_se drop _rcs* drop _d_rcs* tempvar ln_nr_time qui gen double `ln_nr_time' = ln(`nr_time') if `touse' qui rcsgen `ln_nr_time' if `touse', knots(`e(ln_bhknots)') gen(_rcs) dgen(_d_rcs) unab rcsterms :_rcs* unab drcsterms :_d_rcs* if "`e(orthog)'" != "" { mata st_store(.,tokens(st_local("rcsterms")),"`touse'",(st_data(.,tokens(st_local("rcsterms") +" `ocons'"),"`touse'")*luinv(st_matrix("e(R_bh)")))[,1..`e(dfbase)']) mata st_store(.,tokens(st_local("drcsterms")),"`touse'",(st_data(.,tokens(st_local("drcsterms")),"`touse'")*luinv(st_matrix("e(R_bh)"))[1..`e(dfbase)',1..`e(dfbase)'])) } foreach tvcvar in `e(tvc)' { if `e(df_`tvcvar')' == 1 { qui rcsgen `ln_nr_time' if `touse', gen(_rcs_`tvcvar') dgen(_d_rcs_`tvcvar') } else if `e(df_`tvcvar')' != 1 { qui rcsgen `ln_nr_time' if `touse', knots(`e(ln_tvcknots_`tvcvar')') gen(_rcs_`tvcvar') dgen(_d_rcs_`tvcvar') } unab rcsterms_`tvcvar' : _rcs_`tvcvar'* unab drcsterms_`tvcvar' : _d_rcs_`tvcvar'* if "`e(orthog)'" != "" { mata st_store(.,tokens(st_global("e(rcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(rcsterms_`tvcvar')") + " `ocons'" )),"`touse'")*luinv(st_matrix("e(R_`tvcvar')")))[,1..`e(df_`tvcvar')']) mata st_store(.,tokens(st_global("e(drcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(drcsterms_`tvcvar')"))),"`touse'")*luinv(st_matrix("e(R_`tvcvar')"))[1..`e(df_`tvcvar')',1..`e(df_`tvcvar')'])[,1..`e(df_`tvcvar')']) } forvalues k = 1/`e(df_`tvcvar')' { qui replace _rcs_`tvcvar'`k' = _rcs_`tvcvar'`k' * `tvcvar' if `touse' qui replace _d_rcs_`tvcvar'`k' = _d_rcs_`tvcvar'`k' * `tvcvar' if `touse' } } if "`e(scale)'" == "hazard" { qui predictnl double `lnln_s' = xb(xb)`addoff' if `touse', se(`lnln_s_se') } else if "`e(scale)'" == "odds" { qui predictnl double `lnln_s' = ln(ln(1+exp(xb(xb)`addoff'))) if `touse', se(`lnln_s_se') } else if "`e(scale)'" == "normal" { qui predictnl double `lnln_s' = ln(-ln(normal(xb(xb)`addoff'))) if `touse', se(`lnln_s_se') } else if "`e(scale)'" == "theta" { qui predictnl double `lnln_s' = ln(ln(exp(xb(ln_theta))*exp(xb(xb)`addoff')+1)/exp(xb(ln_theta))) if `touse', se(`lnln_s_se') } if "`e(scale)'" == "hazard" { qui predictnl double `h'=(1/(`newvarname'))*(xb(dxb))*exp(xb(xb)`addoff') if `touse' } else if "`e(scale)'" == "odds" { qui predictnl double `h'=1/(`newvarname')*(xb(dxb))*exp(xb(xb)`addoff')/(1+exp(xb(xb)`addoff')) if `touse' } else if "`e(scale)'" == "normal" { qui predictnl double `h'=1/(`newvarname')*(xb(dxb))*normalden(xb(xb)`addoff')/(normal(-(xb(xb)`addoff'))) if `touse' } else if "`e(scale)'" == "theta" { qui predictnl double `h'=1/(`newvarname')*(xb(dxb))*exp(xb(xb)`addoff')/(exp(xb(ln_theta))*exp(xb(xb)`addoff') + 1) if `touse' } tempvar s_tp predict `s_tp' if `touse', s `offset' qui replace `s_tp' = ln(`s_tp') if `touse' qui gen double `tp_se' = `s_tp'*`lnln_s_se'/`h' if `touse' qui gen double `newvarname'_lci = `newvarname' - invnormal(1-0.5*(1-`level'/100))*`tp_se' if `touse' qui gen double `newvarname'_uci = `newvarname' + invnormal(1-0.5*(1-`level'/100))*`tp_se' if `touse' } } /* restore original data and merge in new variables */ local keep `newvarname' if "`ci'" != "" { local keep `keep' `newvarname'_lci `newvarname'_uci } else if "`stdp'" != "" { local keep `keep' `newvarname'_se } keep `keep' qui save `newvars' restore merge using `newvars', _merge(`merge') end /* meansurv added to stpm2_pred as sub program */ * 10March2009 - added averages for models on odds, probit or theta scales. program Stmeancurve, sortpreserve version 10.0 syntax newvarname [if] [in],[TIMEvar(varname) AT(string) noOFFSET] marksample touse, novarlist local newvarname `varlist' tempvar t lnt touse_time preserve /* use timevar option or _t */ if "`timevar'" == "" { qui gen `t' = _t if `touse' qui gen double `lnt' = ln(_t) if `touse' } else { qui gen double `t' = `timevar' if `touse' qui gen double `lnt' = ln(`timevar') if `touse' } /* generate ocons for use when orthogonalising splines */ tempvar ocons gen `ocons' = 1 /* Calculate new spline terms */ if "`timevar'" != "" { drop _rcs* _d_rcs* qui rcsgen `lnt' if `touse', knots(`e(ln_bhknots)') gen(_rcs) if "`e(orthog)'" != "" { mata st_store(.,tokens(st_global("e(rcsterms_base)")),"`touse'",(st_data(.,(tokens(st_global("e(rcsterms_base)") + " `ocons'" )),"`touse'")*luinv(st_matrix("e(R_bh)")))[,1..`e(dfbase)']) } } if "`e(tvc)'" != "" { capture drop _rcs_* } foreach tvcvar in `e(tvc)' { qui rcsgen `lnt' if `touse', gen(_rcs_`tvcvar') knots(`e(ln_tvcknots_`tvcvar')') if "`e(orthog)'" != "" { mata st_store(.,tokens(st_global("e(rcsterms_`tvcvar')")),"`touse'",(st_data(.,(tokens(st_global("e(rcsterms_`tvcvar')") + " `ocons'" )),"`touse'")*luinv(st_matrix("e(R_`tvcvar')")))[,1..`e(df_`tvcvar')']) } } /* index which time units are selected */ gen `touse_time' = `t' != . /* Out of sample predictions using at() */ if "`at'" != "" { tokenize `at' while "`1'"!="" { unab 1: `1' cap confirm var `2' if _rc { cap confirm num `2' if _rc { di in red "invalid at(... `1' `2' ...)" exit 198 } } qui replace `1' = `2' if `touse' mac shift 2 } } foreach tvcvar in `e(tvc)' { local rcstvclist `rcstvclist' `e(rcsterms_`tvcvar')' } if "`e(scale)'" == "theta" { local theta = exp([ln_theta][_cons]) } mata: msurvpop("`newvarname'","`touse'","`touse_time'","`rcstvclist'") /* restore original data and merge in new variables */ local keep `newvarname' if "`ci'" != "" { local keep `keep' `newvarname'_lci `newvarname'_uci } else if "`stdp'" != "" { local keep `keep' `newvarname'_se } keep `keep' tempfile newvars qui save `newvars' restore tempvar merge merge using `newvars', _merge(`merge') end mata: void msurvpop(string scalar newvar, string scalar touse, string scalar touse_time, string scalar tvcrcslist) { /* Transfer data from Stata */ rcsbase = st_data( ., tokens(st_global("e(rcsterms_base)")), touse_time) rcstvc = st_data( ., tokens(tvcrcslist), touse_time) x = st_data(.,tokens(st_global("e(varlist)")),touse) tvcvar = tokens(st_global("e(tvc)")) ntvc = cols(tvcvar) beta = st_matrix("e(b)")'[1..cols(rcsbase)+cols(rcstvc) + cols(tokens(st_global("e(varlist)"))) + 1,1] scale = st_global("e(scale)") if (scale == "theta") theta = strtoreal(st_local("theta")) /* check whether to include offset */ offset_name = st_global("e(offset1)") if (offset_name != "" & st_local("offset") != "nooffset") offset = st_data(.,offset_name,touse) else offset = 0 startstop = J(ntvc,2,.) tvcpos = J(ntvc,1,.) tmpstart = 1 /* Loop over number of time observations */ for (i=1;i<=ntvc;i++){ startstop[i,1] = tmpstart tmpntvc = cols(tokens(st_global("e(rcsterms_"+tvcvar[1,i]+")"))) startstop[i,2] = tmpstart + tmpntvc - 1 tmpstart = startstop[i,2] + 1 pos = . maxindex(tvcvar[1,i]:==tokens(st_global("e(varlist)")),1,pos,.) tvcpos[i,1] = pos } Nx = rows(x) Nt = rows(rcsbase) /* Loop over all selected observations */ meansurv = J(Nt,1,0) for (i=1;i<=Nx;i++) { tmprcs = J(Nt,0,.) for (j=1;j<=ntvc;j++) { tmprcs = tmprcs, rcstvc[,startstop[j,1]..startstop[j,2]]:* x[i,tvcpos[j,1]] } if (scale == "hazard") meansurv = meansurv + exp(-exp((J(Nt,1,x[i,]),rcsbase, tmprcs,J(Nt,1,1))*beta :+ offset)):/Nx else if (scale == "odds") meansurv = meansurv + ((1 :+ exp((J(Nt,1,x[i,]),rcsbase, tmprcs,J(Nt,1,1))*beta :+ offset)):^(-1)):/Nx else if (scale == "normal") meansurv = meansurv + normal(-(J(Nt,1,x[i,]),rcsbase, tmprcs,J(Nt,1,1))*beta :+ offset):/Nx else if (scale == "theta") meansurv = meansurv + ((theta:*exp((J(Nt,1,x[i,]),rcsbase, tmprcs,J(Nt,1,1))*beta :+ offset) :+ 1):^(-1/theta)):/Nx } (void) st_addvar("double",newvar) st_store(., newvar, touse_time,meansurv) } end