*! version 3.1.2 7/04/95 (STB-29: sg29.1) program define smrby version 3.1 local in "opt" local if "opt" local varlist "req ex min(2) max(2) " #delimit ; local options "Level(integer $S_level) BY(string) TOTal TRend Ordinal Hetero"; #delimit cr parse "`*'" parse "`varlist'", parse(" ") if `level'<10 | `level'>99 { di in red "level() invalid" exit 198 } tempvar obs expec quietly { gen `obs'=`1' gen `expec'=`2' count `if' `in' local nobs = _result(1) if `nobs'<1 { noisily di "No observations" exit } if "`by'"!="" { local BY "`by'" local vlbl : val lab `by' local bylbl : var lab `by' if ("`bylbl'" == ""|substr("`bylbl'",13,1)!=""){local bylbl "`by'"} } else {local bylbl ""} local obslbl : var lab `1' if ("`obslbl'" == ""|substr("`obslbl'",11,1)!="") { local obslbl "`1'"} local explbl : var lab `2' if ("`explbl'" == ""|substr("`explbl'",11,1)!="") { local explbl "`2'"} noisily di #delimit ; noisily di in gr _col(15) "Observed" _col(27) "Expected" _col(54) "-- Poisson Exact --"; #delimit cr tempvar touse disp gen byte `touse' = 1 `if' `in' if "`vlbl'"!=""{ tempvar BY decode `by' if `touse' == 1 , gen(`BY') } sort `touse' `by' by `touse' `by':replace `obs'=sum(`obs') by `touse' `by':replace `expec'=sum(`expec') if "`by'"!="" { g `disp'= `touse' if `by'!=`by'[_n+1] } else {g `disp'= 1 if `touse'!=`touse'[_n+1]} sort `disp' `by' count if `disp'==1 local i2 = _result(1) sum `expec' if `disp'==1 local fd = min(7 - int(log(_result(6))/log(10)),4) if "`by'"!=""&("`trend'"!=""|"`hetero'"!=""){ tempvar O E tempname Otot Etot v chitr het mu Omean gen `O'=`obs' in 1/`i2' gen `E'=`expec' in 1/`i2' } #delimit ; noisily di in gr "`bylbl'" _col(13) "| `obslbl'" _col(26) " `explbl'" _col(38) " O/E (%)" _col(54) "[`level'% Conf. Interval]" _n "------------+" _dup(64) "-" ; #delimit cr local i 1 while `i'<=`i2' & `disp'!=. { if "`j'"!="" { replace `obs'=sum(`obs') in 1/`i2' replace `expec'=sum(`expec') in 1/`i2' } local o=`obs'[`i'] local e=`expec'[`i'] if "`by'" != ""{ local site " `BY'[`i'] "} if "`j'"!="" {local site ""Total""} capture confirm integer number `o' if _rc==0 { _crccip `o' `level' local l=100*($S_1/`e') local u=100*($S_2/`e') local r=100*(`o'/`e') local emark "" } else { local l=. local u=. local r=. local emark "&" local aemark "&" } if(`o'==0 & `e'!=0) { local mark "+" local amark "+" } else local mark "" local star "" local p 1 if `l'>100 { local p = gammap(`o',`e')} else if `u'<100 { local p = 1-gammap(`o'+1,`e')} if `p'<.0005 { local star "***" local s3 "*" } else if `p'<.005 { local star "**" local s2 "*" } else if `p'<.025 { local star "*" local s1 "*" } #delimit ; noisily di in gr `site' _col(13) "| " in yel %8.0f `o' _col(26) %9.`fd'f `e' _col(38) %9.1f `r' "`star'" _col(54) %7.0f `l' _col(63) %7.0f `u' in gr "`mark'" "`emark'"; #delimit cr if `i'==`i2' & "`total'"!="" & "`j'"=="" { local i=`i2'-1 local j=`i2' noisily di in gr "------------+" _dup(64) "-" } local i = `i'+1 } if "`by'"!=""&("`trend'"!=""|"`hetero'"!=""){ local btype : type `by' local btype = substr("`btype'",1,3) if "`ordinal'"!=""| "`btype'"=="str" { tempvar ord gen int `ord'=_n in 1/`i2' local byby "`ord'" local ord_st "(coded 1,2,...)" } else {local byby "`by'"} summ `byby' [fweight = `E'] scalar `Etot' = _result(2) scalar `mu' = _result(3) scalar `v' = _result(4) *(`Etot'-1)/`Etot' summ `byby' [fweight = `O'] scalar `Otot' = _result(2) scalar `Omean'= _result(3) if "`trend'"!="" { if "`btype'"=="str" { noi di _n "Trend test not possible on string variable" } else { scalar `v' = `v'/`Otot' scalar `chitr' = ( `Omean' - `mu')^2/`v' noi di in gr _n "Chi-squared for trend `ord_st'" /* */ in ye %8.2f = `chitr' " ( 1 df, p = " in ye %6.3f chiprob(1,`chitr') " )" } } if "`hetero'"!=""{ replace `E' = `E' * `Otot' / `Etot' replace `E'=(`O'-`E')*(`O'-`E')/`E' replace `E'=sum(`E') scalar `het' = `E'[_N] noi di in gr _n "Chisq test for unequal SMRs = " /* */ in ye %8.2f = `het' " (" `i2'-1 " df, p = " %6.3f chiprob(`i2'-1, `het') " )" } } } /* ends quietly */ di _n if "`amark'"!="" { di in gr "(+) one-tail, " 100-(100-`level')/2 /* */ "% confidence interval" } if "`s1'"!="" {di in gr "(*) Twice 1-sided p<.05"} if "`s2'"!="" { di in gr "(**) Twice 1-sided p<.01"} if "`s3'"!="" { di in gr "(***) Twice 1-sided p<.001"} if "`aemark'"!="" { di in gr "(&) Observed count must be an integer." } end