program permtest2, rclass byable(recall) version 9.0 syntax varname [if] [in], BY(varname) [runs(integer -1) exact simulate] marksample touse markout `touse' `by' local x "`varlist'" local simcount=`runs' local mode=0 if "`exact'" != "" & "`simulate'" != "" { di in red "You are not allowed to specify both exact and simulate!" exit 499 } if "`exact'" != "" { if `simcount' != -1 { di in red "You are not allowed to specify both runs() and exact!" exit 499 } local mode=1 } if "`simulate'" != "" { local mode=2 } quietly { summarize `by' if `touse', meanonly if r(N) == 0 { di in red `"No group found, 2 required"' exit 499 } if r(min) == r(max) { di in red `"1 group found, 2 required"' exit 499 } local g1 = r(min) local g2 = r(max) count if `by'!=`g1' & `by'!=`g2' & `touse' if r(N) != 0 { di in red `"more than 2 groups found, only 2 allowed"' exit 499 } } quietly count if `touse' local samplesize = `r(N)' if `samplesize' > `c(matsize)' { if `samplesize' > `c(max_matsize)' { di in red "Your version of stata allows a maximum matrix size of" di in red `c(max_matsize)' ", whereas you need at least a matrix" di in red "size of " `samplesize' " to perform the requested operation." exit 499 } set matsize `samplesize' } quietly sum `x' if `touse' & `by'==`g1' local n1=r(N) local m1=r(mean) local s1=r(sd) quietly sum `x' if `touse' & `by'==`g2' local n2=r(N) local m2=r(mean) local s2=r(sd) quietly sum `x' if `touse' local nc=r(N) local mc=r(mean) local sc=r(sd) if `mode'==0 { if `nc' >15{ local mode=2 } else { local mode=1 } } di in green "Fisher-Pitman permutation test for two independent samples" di _n di in smcl in gr %12s abbrev(`"`by'"',12) " {c |} obs mean std.dev." di in smcl in gr "{hline 13}{c +}{hline 33}" #delimit; di in smcl in gr %12s `"`g1'"' " {c |}" in ye _col(17) %7.0g `n1' _col(26) %10.0g `m1' _col(38) %10.0g `s1' ; di in smcl in gr %12s `"`g2'"' " {c |}" in ye _col(17) %7.0g `n2' _col(26) %10.0g `m2' _col(38) %10.0g `s2' ; di in smcl in gr "{hline 13}{c +}{hline 33}"; di in smcl in gr %12s "combined" " {c |}" in ye _col(17) %7.0g `nc' _col(26) %10.0g `mc' _col(38) %10.0g `sc' ; #delimit cr di _n if `simcount'<0 { local simcount=200000 } di in gr "mode of operation: " _c if `mode'==1 { di in ye "exact (complete permutation)" _n } else { di in ye "Montecarlo simulation (`simcount' runs)" _n } tempname sample mresult mkmat `by' `x' if `touse', matrix(sample) local matrix mresult=(.) mata: permtestIndependent(`g1',`g2',`mode',`simcount') #delimit ; di in green "Test of hypothesis Ho: " "`x'" "(" "`by'" "==" `g1' ") >= " "`x'" "(" "`by'" "==" `g2' ") : p=" in yellow el(mresult,1,1) in green " (one-tailed)"; di in green "Test of hypothesis Ho: " "`x'" "(" "`by'" "==" `g1' ") <= " "`x'" "(" "`by'" "==" `g2' ") : p=" in yellow el(mresult,2,1) in green " (one-tailed)"; di in green "Test of hypothesis Ho: " "`x'" "(" "`by'" "==" `g1' ") == " "`x'" "(" "`by'" "==" `g2' ") : p=" in yellow el(mresult,3,1) in green " (two-tailed)"; #delimit cr return scalar lowertail = el(mresult,1,1) return scalar uppertail = el(mresult,2,1) return scalar twotail = el(mresult,3,1) return scalar n1 = `n1' return scalar n2 = `n2' return scalar criticalValue = el(mresult,6,1) return scalar N = `samplesize' return scalar mode = el(mresult,4,1) return scalar runs = el(mresult,5,1) end mata: version 9.0 void permtestIndependent(g1,g2,real scalar mode, real scalar simct) { smp=st_matrix("sample") smp_string=st_matrixcolstripe("sample") /* generate sign vector */ for (i=1;i<=rows(smp);i++) { if (smp[i,1]==g1) { if (i==1) { sign=1 } else { sign=(sign\1) } } else { if (i==1) { sign=-1 } else { sign=(sign\-1) } } } /* initialize values */ lower=0 higher=0 total=0 threshold=sum(sign:*smp[.,2]) /* do permutations */ m=(.) if (mode==1) { m=genPermutationMatrixInd(sign) simct=1 for (i=1;i<=cols(m);i++) { val=sum(m[.,i]:*smp[.,2]) total++ if (val<=threshold) lower++ if (val>=threshold) higher++ } } else { step=round(simct/40); printf("{text}Progress: {c |}{result}") ts=sign; for (j=1;j<=simct;j++) { if (mod(j,step)==0) { displayflush() printf(".") } _jumble(ts); val=sum(ts:*smp[.,2]) total++ if (val<=threshold) lower++ if (val>=threshold) higher++ } printf("{text}|\n\n") } lt=(lower)/total ut=(higher)/total tt=min((0.5,ut,lt))*2 result=(lt\ut\tt\mode\simct\threshold) st_matrix("mresult",result) } function genPermutationMatrixInd(sign) { m=(.) perminfo=cvpermutesetup(sign) while ((p=cvpermute(perminfo)) != J(0,1,.)) { if ( m==(.)) { m=p } else { m=(m,p) } } return(m); } end