*! version 1.0.0 28apr1999 program define ltable2 version 6 syntax varlist(min=1 max=2) [fw] [if] [in] [, /* */ noAdjust BY(varname) noCONF Connect(string) /* */ Failure Graph Hazard Intervals(string) /* */ Level(integer $S_level) SAving(string) /* */ SUrvival Symbol(string) noTAb Test TVid(varname) /* */ XLAbel(string) YLAbel(string) factor(integer 1) * ] tempvar touse mark `touse' `if' `in' [`weight'`exp'] markout `touse' `by', strok tokenize `varlist' qui count if `touse' if r(N)==0 { error 2000 } if `"`hazard'"'=="" & `"`failure'"'=="" { local surviva "survival" } if `"`graph'"'!="" { if (`"`hazard'"'!="")+(`"`surviva'"'!="")+(`"`failure'"'!="")>1 { error 198 } } if `level'<10 | `level'>99 { local level 95 } tempvar Group I0 I1 dI Total tt td dead lost start atrisk fail tempvar F seF loF upF S loS upS H seH loH upH tempvar sv1 st ss tempvar Imid sellS local t `1' if `"`2'"'=="" { tempvar d quietly gen byte `d'=1 } else local d `2' if `"`exp'"'!="" { tempvar wgt gen long `wgt' `exp' local wvar `wgt' } else local wgt 1 preserve quietly { keep if `touse' drop if `wgt'<=0 drop if `t'==. capture assert `t'>=0 if _rc { noi di in red "time variable has negative values" exit 411 } if `"`tvid'"'!="" { sort `tvid' `t' `d' by `tvid': keep if _n==_N } count if `d'==. if r(N) { noisily di in blu /* */ `"(warning: `d' has missing values; "' /* */ r(N) " obs not used)" drop if `d'==. } local g `by' if `"`g'"'=="" { gen `Group' = 1 local g `"`Group'"' } else { capture drop if `g'==. } if _N==0 { error 2000 } keep `t' `d' `g' `wvar' /* Process intervals or set default intervals */ if `"`interva'"'=="" { local interva 1 } noisily _crcltab `t' `I0' `I1' `"`interva'"' sort `g' `I0' `t' /*-------------------- CALCULATE STATISTICS -------------------------*/ by `g': gen `Total'= sum(`wgt') by `g': replace `Total'=`Total'[_N] by `g': gen `tt' = sum(`wgt'*`t') by `g': gen `td' = sum(`wgt'*(`d'!=0)) by `g' `I0': gen `dead' = sum(`wgt'*(`d'!=0)) by `g' `I0': gen `lost' = sum(`wgt') by `g' `I0': keep if _n==_N local gtot=_N gen `start' = `Total' drop `Total' by `g': replace `start' = `start'[_n-1]-`lost'[_n-1] if _n>1 if `"`adjust'"'=="" { gen double `atrisk' = `start'-(`lost'-`dead')/2 } else gen double `atrisk' = `start' gen double `fail' = `dead'/`atrisk' /* Hazard calculation */ gen `dI' = `I1'-`I0' if `"`adjust'"'=="" { gen `H' = 2*`fail'/((2-`fail')*`dI') gen `seH' = `H'*sqrt((1-(`dI'*`H'/2)^2) /* */ / (`atrisk'*`fail')) } else { gen `H' = `fail'/`dI' gen `seH' = `H'/sqrt(`dead') } /* Fail calculation */ gen double `S'=. by `g': replace `S'=cond(_n==1,1,`S'[_n-1])*(1-`fail') gen `F' = 1-`S' by `g': gen `sv1' = sum(`fail'/(`atrisk'-`dead')) by `g': gen `seF' = `S'*sqrt(`sv1') if `S'!=0 by `g': gen `sellS'= /* */ sqrt(sum(`dead'/(`atrisk'*(`atrisk'-`dead'))) / /* */ (sum(ln((`atrisk'-`dead')/`atrisk'))^2)) local iz=invnorm(1-(1-`level'/100)/2) gen `upS' = `S'^exp(-`iz'*`sellS') if `S'!=0 gen `loS' = `S'^exp(`iz'*`sellS') if `S'!=0 *gen `upS' = max(min(`S'+`iz'*`seF',1),0) *gen `loS' = max(min(`S'-`iz'*`seF',1),0) gen `upF' = 1-`loS' gen `loF' = 1-`upS' * gen `upF' = max(min(`F'+`iz'*`seF',1),0) * gen `loF' = max(min(`F'-`iz'*`seF',1),0) if `"`adjust'"'=="" { gen `upH' = `H'+`iz'*`seH' gen `loH' = `H'-`iz'*`seH' } else { gen `upH' = (`H'/`dead') /* */ *invgammap(`dead',(1+`level'/100)/2) gen `loH' = (`H'/`dead') /* */ *invgammap(`dead',(1-`level'/100)/2) } replace `upH'=0 if `upH'<0 replace `loH'=0 if `loH'<0 /*------------------------- GRAPH -----------------------------------*/ if `"`graph'"'!="" { if `"`saving'"'!="" { local saving `"saving(`saving')"' } local tlbl : var label `t' if `"`tlbl'"'=="" { local tlbl `"`t'"' } label var `I1' `"`tlbl'"' if `"`connect'"'=="" { local connect "c(l||)" } else { local connect `"c(`connect'||)"' } if `"`symbol'"'=="" { local symbol O } if `"`xlabel'"'=="" { local xlabel xlab } else local xlabel `"xlab(`xlabel')"' if `"`ylabel'"'=="" { local ylabel ylab } else local ylabel `"ylab(`ylabel')"' if `"`failure'"'!="" { label var `F' "Proportion Failed" if `"`conf'"'=="" { noisily gr `F' `upF' `loF' `I1',/* */ by(`g') `connect' s(`symbol'ii) /* */ `xlabel' `ylabel' `saving' `options' } else { noisily gr `F' `I1',/* */ by(`g') `connect' s(`symbol') /* */ `xlabel' `ylabel' `saving' `options' } } else if `"`surviva'"'!="" { label var `S' "Proportion Surviving" if `"`conf'"'=="" { noisily gr `S' `upS' `loS' `I1',/* */ by(`g') `connect' s(`symbol'ii) /* */ `xlabel' `ylabel' `saving' `options' } else { noisily gr `S' `I1',/* */ by(`g') `connect' s(`symbol') /* */ `xlabel' `ylabel' `saving' `options' } } else { label var `H' "Hazard" gen `Imid'=(`I0'+`I1')/2 label var `Imid' `"`tlbl'"' if `"`conf'"'=="" { noisily gr `H' `upH' `loH' `Imid',/* */ by(`g') `connect' s(`symbol'ii) /* */ `xlabel' `ylabel' `saving' `options' } else { noisily gr `H' `Imid',/* */ by(`g') `connect' s(`symbol') /* */ `xlabel' `ylabel' `saving' `options' } drop `Imid' } } /*---------------------- TABLE PRESENTATION ----------------*/ if `"`surviva'"'!="" & `"`tab'"'=="" { #delimit ; noisily di _n in gr _col(18) "Beg." _col(55) "Std." _n _col( 4) "Interval" _col(17) "Total" _col(25) "Deaths" _col(34) "Lost" _col(42) "Survival" _col(54) "Error" _col(64) `"[`level'% Conf. Int.]"' _n _dup(79) "-" ; #delimit cr local i 1 while `i'<=_N { if `"`g'"'~=`"`Group'"' & `g'[`i']!=`g'[`i'-1] { * noisily di in gr `"`g' "' `g'[`i'] noisily Ghdr "`g'" `i' } #delimit ; noisily di in gr %5.0f `I0'[`i'] %6.0f `I1'[`i'] in ye %10.0f `start'[`i'] %9.0f `dead'[`i'] %7.0f `lost'[`i']-`dead'[`i'] %11.4f `S'[`i']*`factor' %10.4f `seF'[`i']*`factor' %11.4f `loS'[`i']*`factor' %10.4f `upS'[`i']*`factor' ; #delimit cr local i=`i'+1 } noi di in gr _dup(79) "-" } if `"`failure'"'!="" & `"`tab'"'=="" { #delimit ; noisily di _n in gr _col(18) "Beg." _col(44) "Cum." _col(55) "Std." _n _col( 4) "Interval" _col(17) "Total" _col(25) "Deaths" _col(34) "Lost" _col(42) "Failure" _col(54) "Error" _col(64) `"[`level'% Conf. Int.]"' _n _dup(79) "-" ; #delimit cr local i 1 while `i'<=_N { if `"`g'"'~=`"`Group'"' & `g'[`i']!=`g'[`i'-1] { noisily di in gr `"`g' "' `g'[`i'] } #delimit ; noisily di in gr %5.0f `I0'[`i'] %6.0f `I1'[`i'] in ye %10.0f `start'[`i'] %9.0f `dead'[`i'] %7.0f `lost'[`i']-`dead'[`i'] %11.4f `F'[`i']*`factor' %10.4f `seF'[`i']*`factor' %11.4f `loF'[`i']*`factor' %10.4f `upF'[`i']*`factor' ; #delimit cr local i=`i'+1 } noi di in gr _dup(79) "-" } if `"`hazard'"'!="" & `"`tab'"'=="" { #delimit ; noisily di _n in gr _col(18) "Beg." _col(27) "Cum." _col(36) "Std." _col(56) "Std." _n _col( 4) "Interval" _col(17) "Total" _col(25) "Failure" _col(35) "Error" _col(44) "Hazard" _col(55) "Error" _col(64) `"[`level'% Conf. Int.]"' _n _dup(79) "-" ; #delimit cr local i 1 while `i'<=_N { if `"`g'"'~=`"`Group'"' & `g'[`i']!=`g'[`i'-1] { noisily di in gr `"`g' "' `g'[`i'] } #delimit ; noisily di in gr %5.0f `I0'[`i'] %6.0f `I1'[`i'] %10.0f `start'[`i'] %10.4f `F'[`i']*`factor' %8.4f `seF'[`i']*`factor' in ye %10.4f `H'[`i'] *`factor' %10.4f `seH'[`i']*`factor' %10.4f `loH'[`i']*`factor' %10.4f `upH'[`i']*`factor' ; #delimit cr local i=`i'+1 } noi di in gr _dup(79) "-" } if `factor'~=1 { noi di in gr "(rates multiplied by `factor')" } /*--------------FIRST SET OF CHI SQUARE STATISICS -------------------*/ if `"`g'"'~=`"`Group'"' & `"`test'"'!="" { by `g': keep if _n==_N gen `st'=sum(`td')*log(sum(`tt')/sum(`td')) gen `ss'= sum(`td'*log(`tt'/`td')) local chi2=2*(`st'[_N]-`ss'[_N]) #delimit ; noisily di _n(2) in gr "Likelihood-ratio test statistic of homogeneity " `"(group=`g'):"' _n "chi2( " in ye _N-1 /* df */ in gr " ) = " in ye `chi2' in gr ", P = " in ye chiprob(_N-1,`chi2') ; #delimit cr /*------------- SECOND SET OF CHI SQUARE STATISICS ------------------*/ restore if `"`exp'"'!="" { local wtopt= "[`weight'`exp']" } noisily di " " noisily di in gr /* */ `"Logrank test of homogeneity (group=`g'):"' noisily logrank `t' `d' `wtopt' if `touse', by(`g') } } end program define _crcltab version 3.0 local t "`1'" local I0 "`2'" local I1 "`3'" local interva "`4'" if "`interva'"=="w" { _crcltab `t' `I0' `I1' "0 7 15 30 60 90 180 360 540 720" exit } parse "`interva'", parse(", ") quietly gen float `I0'=0 quietly gen float `I1'=. if "`2'"=="" { confirm number `1' if `1'<=0 | `1'== . { di in red "interval() invalid" exit 198 } quietly replace `I0' = int(`t'/`1')*`1' quietly replace `I1' = `I0'+`1' exit } local last -1 while "`1'"!="" { if "`1'"!="," { confirm number `1' if `1'<=`last' { di in red "intervals must be ascending" exit 198 } if `last'!= -1 { quietly replace `I0'=`last' /* */ if `t'>=`last' & `t'<`1' quietly replace `I1'=`1' /* */ if `t'>=`last' & `t'<`1' } local last `1' } mac shift } if `last'==0 { di in red "intervals invalid" exit 198 } quietly replace `I0'=`last' if `t'>=`last' quietly replace `I1'=. if `t'>=`last' end program define Ghdr /* varname idx */ args varname i local typ : type `varname' if substr("`typ'",1,3)=="str" { di in ye `varname'[`i'] exit } local val = `varname'[`i'] local new : label (`varname') `val' if "`val'" != `"`new'"' { di in ye `"`new'"' exit } local fmt : format `varname' local res : di `fmt' `val' local res = trim(`"`res'"') di in ye `"`varname' = `res'"' end