SUPPLEMENTARY MATERIAL: CODE FOR ANALYSES OF THE DENTAL PAIN DATA ----------------------------------------------------------------- The code below performs multiple imputation analyses of the dental pain data - in SAS and R, in both of which perfect prediction leads to misleading results, - and in Stata, where perfect prediction is handled by the Normal/augment method. In each case, p1-p10 are the outcome variables, t1-t7 are indicators of randomisation to treatments 1-7, and t1p5=t1*p5 etc. The code exploits the fact that variables p1-p5 are complete. === SAS code === /* We used version 9.1.3 of SAS. In this code, randomised group is held in a 7-level variable treat as well as in indicator variables t1-t7. */ proc mi data=dental seed=1 out=imputed nimpute=100; class treat p1 p2 p3 p4 p5 p6 p7 p8 p9 p10; monotone logistic(p6 = p5 treat p5*treat); monotone logistic(p7 = p6 treat p6*treat); monotone logistic(p8 = p7 treat p7*treat); monotone logistic(p9 = p8 treat p8*treat); monotone logistic(p10= p9 treat p9*treat); var treat p1 p2 p3 p4 p5 p6 p7 p8 p9 p10; run; proc genmod data=imputed descending; model p10 = t1 t2 t3 t4 t5 t6 t7 / covb d=bin noint; by _Imputation_; ods output ParameterEstimates=gmparms ParmInfo=gmpinfo CovB=gmcovb; run; data gmpinfo; set gmpinfo; if Effect ne "Intercept"; run; proc mianalyze parms=gmparms covb=gmcovb parminfo=gmpinfo; modeleffects t1 t2 t3 t4 t5 t6 t7; run; === R code === # We used version 1.16 of the MICE library. set.seed(100) library(mice) library(foreign) dental<-read.dta("c:/dental pain/dental.dta") dental<-data.frame(dental) attach(dental) mpred<-matrix(0,43,43) rt<-t(matrix(c(c(1,1,1,1,1,1,0),diag(7)),7,8)) rp<-diag(5) for (i in c(1:5)) { a<-c(rt[1,],rp[i,],0) for (j in c(1:6)) {a<-c(a,rp[i,])} mpred[i+8,]<-a } for (j in c(1:6)) { for (i in c(1:5)) {mpred[13+i+5*(j-1),]<-c(rt[j+1,],rp[i,],matrix(0,1,31))} } imp<-mice(dental,m=100, im=c("","","","","","","","","logreg","logreg","logreg","logreg","logreg", "","~I(t1*p6)","~I(t1*p7)","~I(t1*p8)","~I(t1*p9)", "","~I(t2*p6)","~I(t2*p7)","~I(t2*p8)","~I(t2*p9)", "","~I(t3*p6)","~I(t3*p7)","~I(t3*p8)","~I(t3*p9)", "","~I(t4*p6)","~I(t4*p7)","~I(t4*p8)","~I(t4*p9)", "","~I(t5*p6)","~I(t5*p7)","~I(t5*p8)","~I(t5*p9)", "","~I(t6*p6)","~I(t6*p7)","~I(t6*p8)","~I(t6*p9)"), predictorMatrix=mpred) completed<-complete(imp,action="long") write.table(completed,file="c://dental pain//Rimps.txt", append=FALSE,quote=FALSE,row.names=FALSE,col.names=FALSE) fit<-glm.mids(p10~t1+t2+t3+t4+t5+t6+t7-1, imp, family=binomial(link=logit)) result<-pool(fit) result$qbar sqrt(diag(result$t)) === Stata code === /* The following code implements the Normal/augment method in all versions of ice from version 1.4.3. */ #delimit ; ice t1 t2 t3 t4 t5 t6 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 t1p5 t1p6 t1p7 t1p8 t1p9 t2p5 t2p6 t2p7 t2p8 t2p9 t3p5 t3p6 t3p7 t3p8 t3p9 t4p5 t4p6 t4p7 t4p8 t4p9 t5p5 t5p6 t5p7 t5p8 t5p9 t6p5 t6p6 t6p7 t6p8 t6p9, m(100) clear cycles(1) eq(p6:t1 t2 t3 t4 t5 t6 p5 t1p5 t2p5 t3p5 t4p5 t5p5 t6p5, p7:t1 t2 t3 t4 t5 t6 p6 t1p6 t2p6 t3p6 t4p6 t5p6 t6p6, p8:t1 t2 t3 t4 t5 t6 p7 t1p7 t2p7 t3p7 t4p7 t5p7 t6p7, p9:t1 t2 t3 t4 t5 t6 p8 t1p8 t2p8 t3p8 t4p8 t5p8 t6p8, p10:t1 t2 t3 t4 t5 t6 p9 t1p9 t2p9 t3p9 t4p9 t5p9 t6p9) passive(t1p6:t1*p6 \ t1p7:t1*p7 \ t1p8:t1*p8 \ t1p9:t1*p9 \ t2p6:t2*p6 \ t2p7:t2*p7 \ t2p8:t2*p8 \ t2p9:t2*p9 \ t3p6:t3*p6 \ t3p7:t3*p7 \ t3p8:t3*p8 \ t3p9:t3*p9 \ t4p6:t4*p6 \ t4p7:t4*p7 \ t4p8:t4*p8 \ t4p9:t4*p9 \ t5p6:t5*p6 \ t5p7:t5*p7 \ t5p8:t5*p8 \ t5p9:t5*p9 \ t6p6:t6*p6 \ t6p7:t6*p7 \ t6p8:t6*p8 \ t6p9:t6*p9); gen t7=1-t1-t2-t3-t4-t5-t6; mim: logit p10 t1 t2 t3 t4 t5 t6 t7, nocons; === END ===