*! version 2.0 N.Orsini, I. Buchan, 25 Jan 06 *! version 1.0 N.Orsini, J.Higgins, M.Bottai, 16 Feb 2005 capture program drop heterogi program heterogi, rclass version 8 syntax anything [, Level(int $S_level) Format(string) NCchi2 ] tempname Q K df H2 I2 SElnH LB_H_III UB_H_III I22 levelci clevelci tokenize "`anything'" scalar `Q' = `1' scalar `df' = `2' scalar `K' = `df' + 1 /* CHECK ARGUMENTS */ if `Q' < 0 { di in r "Q must be positive" exit 198 } if `df' < 2 { di in r "df must be at least 2" exit 198 } if `level' <10 | `level'>99 { di in red "level() invalid" exit 198 } scalar `levelci' = `level' * 0.005 + 0.50 scalar `clevelci' = 1- `levelci' if "`format'" == "" { local formatI2 = "%4.0f" local formatH = "%4.1f" } else { local formatI2 = "`format'" local formatH = "`format'" } preserve /* COMPUTE INTERVAL */ scalar `H2' = `Q'/`df' scalar `I2' = max(0, (100*(`Q' -`df')/(`Q' )) ) scalar `I22' = max(0, (`H2'-1)/`H2') if sqrt(`H2') < 1 scalar `H2' = 1 * CI for H (Higgins & Thompson, Stats in Medicine 2002) if `Q' > `K' { scalar `SElnH' = .5*[ (log(`Q')-ln(`df')) / ( sqrt(2*`Q') - sqrt(2*`K'-3) ) ] } else { scalar `SElnH' = sqrt( ( 1/(2*(`K'-2) )*(1-1/(3*(`K'-2)^2)) ) ) } scalar `LB_H_III' = exp( log(sqrt(`H2')) - invnorm(`levelci') * `SElnH' ) scalar `UB_H_III' = exp( log(sqrt(`H2')) + invnorm(`levelci') * `SElnH' ) if `LB_H_III' < 1 scalar `LB_H_III' = 1 * CI interval for I2 based var(logH), formula not indicated in (Higgins & Thompson, Stats in Medicine) tempname varI2 lb_I2 ub_I2 lb_I22 ub_I22 scalar `varI2' = 4*`SElnH'^2/exp(4*log(sqrt(`H2'))) scalar `lb_I2' = `I22'-invnorm(`levelci')*sqrt(`varI2') scalar `ub_I2' = `I22'+invnorm(`levelci')*sqrt(`varI2') if `lb_I2' < 0 { scalar `lb_I2' = 0 } if `ub_I2' > 1 { scalar `ub_I2' = 1 } if `c(N)' < 10 qui set obs 10 if "`ncchi2'" != "" { tempname UB_NC LB_NC LB_H_H UB_H_H LB_I2_H UB_I2_H nc * seek ci for non-centrality parameter (nc=q-df), thence for h and i-square scalar `nc' = max(0, `Q' - `df') * check if q < df , in this case no need to seek the lower bound if `Q' < `df' { gen `LB_NC' = 0 } else { gen `LB_NC' = invnchi2(`df',`nc',`clevelci') } gen `UB_NC' = invnchi2(`df',`nc',`levelci') scalar `LB_H_H' = max(1, sqrt(`LB_NC'/`df') ) scalar `LB_I2_H' = max(0, (`LB_H_H'^2 - 1)/`LB_H_H'^2 ) scalar `UB_H_H' = sqrt(`UB_NC'/`df') scalar `UB_I2_H' = (`UB_H_H'^2 - 1)/`UB_H_H'^2 } // end option ncchi2 * preparing variables to be displayed with tabdisp tempname LB_I2_HT UB_I2_HT scalar `LB_I2_HT' = max(0,(`LB_H_III'^2-1)/`LB_H_III'^2) scalar `UB_I2_HT' = (`UB_H_III'^2-1)/`UB_H_III'^2 tempvar a b c d e quietly { gen `e' = "" gen `d' = "" gen `c' = "" label var `d' "Statistic" label var `e' " " egen `a' = seq(), from(1) to(2) block(2) egen `b' = seq(), to(2) replace `d' = "H" if `a' == 1 replace `d' = "I^2" if `a' == 2 replace `e' = "Estimate" if `b' == 1 replace `e' = "[`level'% Conf. Interval]" if `b' == 2 if "`ncchi2'" != "" { replace `c' = string(sqrt(`H2'),"`formatH'") if `a' == 1 & `b' == 1 replace `c' = string(`LB_H_H',"`formatH'") + " " + string(`UB_H_H',"`formatH'") if `a' == 1 & `b' == 2 replace `c' = string(`I22'*100,"`formatI2'") if `a' == 2 & `b' == 1 replace `c' = string(`LB_I2_H'*100,"`formatI2'") + " " + string(`UB_I2_H'*100,"`formatI2'") if `a' ==2 & `b' == 2 } else { replace `c' = string(sqrt(`H2'),"`formatH'") if `a' == 1 & `b' == 1 replace `c' = string(`LB_H_III', "`formatH'") + " " + string(`UB_H_III',"`formatH'") if `a' == 1 & `b' == 2 replace `c' = string(`I22'*100,"`formatI2'") if `a' == 2 & `b' == 1 replace `c' = string(`LB_I2_HT'*100, "`formatI2'") + " " + string(`UB_I2_HT'*100,"`formatI2'") if `a' == 2 & `b' == 2 } } tabdisp `d' `e' , cell(`c') center di as text "Q-test = " as res `Q' as text " d.f. = " as res `df' as text " p-value = " as res %5.4f chiprob(`df', `Q') * return saved scalars return local cmd = "heterogi2" return scalar Q = `Q' return scalar df = `df' return scalar pval = chiprob(`df', `Q') return scalar H = sqrt(`H2') return scalar lb_H_M1 = `LB_H_III' return scalar ub_H_M1 = `UB_H_III' return scalar lb_I2_M1 = `LB_I2_HT' return scalar ub_I2_M1 = `UB_I2_HT' return scalar I2 = `I22' if "`ncchi2'" != "" { return scalar lb_H_M2 = `LB_H_H' return scalar ub_H_M2 = `UB_H_H' return scalar lb_I2_M2 = `LB_I2_H' return scalar ub_I2_M2 = `UB_I2_H' return scalar lb_ncp = max(0,`LB_NC') return scalar ub_ncp = `UB_NC' } end