*! version 1.1 18May2015 // 19/5/2015 PCL: tidied up numeric integration & added some error checks. program define stpm2cif version 11.1 syntax newvarlist (min=2 max=10), CAUSE1(string) CAUSE2(string) /// [CAUSE3(string) CAUSE4(string) CAUSE5(string) /// CAUSE6(string) CAUSE7(string) CAUSE8(string) /// CAUSE9(string) CAUSE10(string) OBS(int 1000) CI MINT(string) /// MAXT(real -99) TIMEname(string) HAZard CONTMORT CONTHAZ ITERATE(int 100)] local newvarlist `varlist' tokenize `newvarlist' local i=0 while "`1'"!="" { local i=`i'+1 local newvar`i' `1' mac shift 1 } // Check that timename doesn't already exist if option is used.*** if "`timename'"!=""{ capture confirm variable `timename' if _rc==0 { di as err "`timename' already exists in the dataset" exit } } else { capture drop _newt } // Count how many causes of death have been specified. local n=2 forvalues i=3/10 { if "`cause`i''"!="" { local n=`n'+1 } } // check variables do no already exist forvalues i = 1/`n' { capture confirm var CIF_`newvar`i'' if _rc == 0 { di as error "Variables CIF_`newvar`i'' already exists" exit 198 } if "`ci'" != "" { capture confirm var CIF_`newvar`i''_lci if _rc == 0 { di as error "Variables CIF_`newvar`i''_lci already exists" exit 198 } capture confirm var CIF_`newvar`i''_uci if _rc == 0 { di as error "Variables CIF_`newvar`i''_uci already exists" exit 198 } } } // Set default time according to _t from stset. if "`mint'" != "" { di as text "Warning: The mint() option is now redundant" } if "`maxt'"=="-99" { qui sum _t local maxt=r(max) } //Save tvc variables in local macro.*** local etvc `e(tvc)' //Count how many variables have been specified for each cause and store in local macros. forvalues i=1/`n' { local varcount`i' : word count `cause`i'' local count`i'=`varcount`i''/2 local j=0 tokenize `cause`i'' while "`1'"!="" { local j=`j'+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 } } local cov`i'`j' `1' local covval`i'`j' `2' mac shift 2 } } //Create a tempfile. tempfile ind preserve drop _all qui set obs `obs' tempvar t //Calculate length of interval.*** local step = `maxt'/(`obs') range `t' `step' `maxt' tempvar lnt qui gen double `lnt' = ln(`t') //Calculate baseline splines. if "`e(rcsbaseoff)'" == "" { capture drop _rcs`i'* _d_rcs`i'* if "`e(orthog)'" != "" { matrix R = e(R_bh) local rmatrix rmatrix(R) } qui rcsgen `lnt', knots(`e(ln_bhknots)') gen(_rcs) dgen(_d_rcs) `e(reverse)' `rmatrix' forvalues i=1/`e(dfbase)' { local rcs `rcs' [xb][_rcs`i']*_rcs`i' local d_rcs `d_rcs' [dxb][_d_rcs`i']*_d_rcs`i' if `i'!=`e(dfbase)' { local rcs `rcs' + local d_rcs `d_rcs' + } } } //Find out how many tvc term there are for each cause forvalues i=1/`n' { local p=0 forvalues j=1/`count`i'' { if `"`: list posof `"`cov`i'`j''"' in etvc'"' != "0" { local p=`p'+1 } } local tvcno`i'=`p' } //Store splines in local macros for each cause of death forvalues i=1/`n' { if "`e(rcsbaseoff)'" == "" { local rcs`i' `rcs`i'' `rcs' local d_rcs`i' `d_rcs`i'' `d_rcs' } local m=0 forvalues j=1/`count`i'' { local p=`m' if `"`: list posof `"`cov`i'`j''"' in etvc'"' != "0" { local m=`m'+1 if `m'==1 & "`e(rcsbaseoff)'" == "" { local rcs`i' `rcs`i'' + local d_rcs`i' `d_rcs`i'' + } local tvcvar`i'`j' `cov`i'`j'' capture drop _rcs_`tvcvar`i'`j''* _d_rcs_`tvcvar`i'`j''* if "`e(orthog)'" != "" { matrix R`i'`j' = e(R_`tvcvar`i'`j'') local rmatrix rmatrix(R`i'`j') } qui rcsgen `lnt', knots(`e(ln_tvcknots_`tvcvar`i'`j'')') gen(_rcs_`tvcvar`i'`j'') /// dgen(_d_rcs_`tvcvar`i'`j'') `e(reverse)' `rmatrix' forvalues l = 1/`e(df_`tvcvar`i'`j'')' { local rcs`i'`j' `rcs`i'`j'' ([xb][_rcs_`tvcvar`i'`j''`l']*_rcs_`tvcvar`i'`j''`l' *`covval`i'`j'') local d_rcs`i'`j' `d_rcs`i'`j'' ([dxb][_d_rcs_`tvcvar`i'`j''`l']*_d_rcs_`tvcvar`i'`j''`l' *`covval`i'`j'') if `l'!=`e(df_`tvcvar`i'`j'')' { local rcs`i'`j' `rcs`i'`j'' + local d_rcs`i'`j' `d_rcs`i'`j'' + } } } if `p'!=`m' { local rcs`i' `rcs`i'' `rcs`i'`j'' local d_rcs`i' `d_rcs`i'' `d_rcs`i'`j'' if `m'!=`tvcno`i'' { local rcs`i' `rcs`i'' + local d_rcs`i' `d_rcs`i'' + } } } //Add constant to splines macro if nocons option is not specified with stpm2.*** if "`e(noconstant)'" == "" { local rcs`i' `rcs`i'' + [xb][_cons] } } //Store covariates in local macros for each cause of death.*** forvalues i=1/`n' { forvalues j=1/`count`i'' { local covs`i' `covs`i'' ([xb][`cov`i'`j'']*`covval`i'`j'') if `j'!=`count`i'' { local covs`i' `covs`i'' + } } } //Calculate overall survival function.*** forvalues i=1/`n' { local xb`i' `covs`i''+`rcs`i'' local surv_all `surv_all' exp(-exp(`xb`i''))* if "`ci'" != "" { local g`newvar`i'' g(_d`newvar`i'') } } gen tothaz = 0 gen totcif = 0 //Calculate hazard function.*** forvalues i=1/`n' { local h_`newvar`i'' (1/`t')*(`d_rcs`i'')*exp(`xb`i'') //Predict integral for each cause of death.*** tempvar f_`newvar`i'' qui predictnl `f_`newvar`i''' = `surv_all'`h_`newvar`i''', `g`newvar`i''' force iterate(`iterate') //Calculate cumulative incidence for each cause of death.*** ********************* //qui gen CIF_`newvar`i'' = sum(`step'*`f_`newvar`i''') qui gen h_`newvar`i'' = (1/`t')*(`d_rcs`i'')*exp(`xb`i'') if "`ci'" != "" { unab d`newvar`i'': _d`newvar`i''* foreach var in `d`newvar`i''' { local add = subinstr("`var'","_d`newvar`i''","",1) local d`newvar`i''coeffnum `d`newvar`i''coeffnum' `add' } } mata: genci("`newvar`i''") if "`hazard'"!="" { local CIF `CIF' CIF_`newvar`i'' h_`newvar`i'' } if "`hazard'"=="" { local CIF `CIF' CIF_`newvar`i'' } qui replace totcif = totcif + CIF_`newvar`i'' qui replace tothaz = tothaz + h_`newvar`i'' } if "`ci'" != "" { forvalues i=1/`n' { qui gen CIF_`newvar`i''_uci = CIF_`newvar`i'' + 1.96*sqrt(`newvar`i''_var) qui gen CIF_`newvar`i''_lci = CIF_`newvar`i'' - 1.96*sqrt(`newvar`i''_var) //Store confidence intervals in local macro.*** local CI `CI' CIF_`newvar`i''_lci CIF_`newvar`i''_uci } } forvalues i=1/`n' { if "`contmort'"!="" { qui gen contmort_`newvar`i''=CIF_`newvar`i''/totcif local cmort `cmort' contmort_`newvar`i'' } if "`conthaz'"!="" { qui gen conthaz_`newvar`i''=h_`newvar`i''/tothaz local chaz `chaz' conthaz_`newvar`i'' } } //Change label for time if timename option specified.*** if "`timename'"!="" { gen `timename'=`t' keep `timename' `CIF' `CI' `chaz' `cmort' } if "`timename'"=="" { gen _newt=`t' keep _newt `CIF' `CI' `chaz' `cmort' } //Restore original dataset and merge with tempfile.*** qui save `ind' restore qui merge 1:1 _n using `ind', nogenerate end ***Mata command used to generate CIF and confidence intervals.*** set matastrict off mata: void genci(string scalar name) { f = st_data(.,st_local("f_"+name)) if(st_local("ci") != "") { gname = st_data(.,tokens(st_local("d"+name))) V = st_matrix("e(V)") } // CIF_name = st_data(.,"CIF_"+name) L = lowertriangle(J(strtoreal(st_local("obs")), strtoreal(st_local("obs")), strtoreal(st_local("step"))), 0.5*strtoreal(st_local("step"))) L[1,1] = strtoreal(st_local("step")) (void) st_addvar("double","CIF_"+name) st_store(., "CIF_"+name, L*f) if(st_local("ci") != "") { (void) st_addvar("double",name+"_var") Vindex = strtoreal(tokens(st_local("d"+name+"coeffnum"))) st_store(.,name+"_var", diagonal(L*gname*V[Vindex,Vindex]*gname'*L')) } } end