/*Program to estimate power for linear ITS designs with no autocorrelation*/ /*v1.0.0 13 Apr 2018*/ program define itspower, rclass /*stata version define*/ version 14.1 /*command syntax*/ syntax, sn(integer) nuts(integer) lvlmn(real) prepoints(integer) sd(string) corr(string) /* */ [lvlsd(real 0) clvl(real 95) seed(integer -127) moreon] /*INPUTS-model mandatory*/ //number of simulations local simnum=`sn' //number of units to be evaluated local numuts=`nuts' //effect to be identified (ITS level change) local lvlmn=`lvlmn' if `lvlmn'==0 { di as error "Level change cannot be zero" error 197 } //number of pre-intervention time points local numpts=`prepoints' if `numpts'<2 { di as error "A minimum of two pre-intervention time-points are required" error 197 } /*INPUTS-model mandatory => vectors*/ //correlations if "`corr'"=="" { di as error "Correlation matrix needs to be provided for each of the `numpts'+1=``numpts'+1' time points" error 197 } //SDs if "`sd'"=="" { di as error "Standard deviation matrix needs to be provided for each of the `numpts'+1=``numpts'+1' time points" error 197 } /*INPUTS-general optional*/ //normaly distributed level change if `lvlsd'<0 { di as error "lvlsd needs to be positive or zero, since it is a the SD for the level change" error 197 } //level scalar clvl=`clvl' set level `=clvl' //seed if `seed'!=-127 { set seed `seed' } //display options set more off if "`moreon'"!="" { set more on } //string for drawnorm, based on number of time points local txtdrnrm = "" forvalues i=1(1)`=`numpts'+1' { local txtdrnrm = "`txtdrnrm' v`i'" } //counter local cntr=0 //display di _newline(2) as text "`numpts' pre-intervention time points. Power to detect a(n) `lvlmn' unit jump due to intervention" di "Iterations (50s):" //loop forvalues i=1(1)`simnum' { clear qui drawnorm `txtdrnrm', n(`numuts') corr(`corr') sd(`sd') //make changes to mean levels and SD qui gen t1=rnormal(`lvlmn',`lvlsd') qui replace v`=`numpts'+1'=v`=`numpts'+1'+t1 qui egen id=seq() //reshape long qui reshape long v, i(id) j(time) rename v outc //regression and prediction qui xtset id qui xtreg outc time if time<=`numpts' qui predict prd if time==`=`numpts'+1', xb //compare prediction to observed qui gen fvar=outc-prd qui ttest fvar==0 //if positive mean difference and statistically sig if `lvlmn'>0 { if r(p)<`=(1-`clvl'/100)' & r(mu_1)>0 { local cntr=`cntr'+1 } } //if negative mean difference and statistically sig else { if r(p)<`=(1-`clvl'/100)' & r(mu_1)<0 { local cntr=`cntr'+1 } } //display if mod(`i',50)==0 { di "." _continue } if mod(`i',2500)==0 { di } } local pwrclc = 100*`cntr'/`simnum' di _newline(2) as text "%Power: " as result %4.1f `pwrclc' local plower = 100*(`pwrclc'/100-invnormal(`=1-(1-`clvl'/100)/2')*sqrt(`pwrclc'/100*(1-`pwrclc'/100)/`simnum')) local pupper = 100*(`pwrclc'/100+invnormal(`=1-(1-`clvl'/100)/2')*sqrt(`pwrclc'/100*(1-`pwrclc'/100)/`simnum')) di as text "`clvl'%CI: " as result %4.1f `plower' as text " to " as result %4.1f `pupper' /*RETURN SCALARS*/ return scalar pow = `pwrclc' return scalar lpow = `plower' return scalar upow = `pupper' end