<p>Appendix V: The SAS Macro bismm</p><p>/*BISMM function by using Interactive Matrix Language (IML) */ /*Converted from R by Bing Cai*/ /*Modified, 01/30/2011, by Daohang Sha */ /*Last modified: go through TTH comments, 02/14/2011, by Daohang Sha */ /*08/31/2011, cleaned up from bismm_no_excl_restrict1.sas by Daohang Sha*/ /*09/02/2011, added notes for multiple baseline covariates, Daohang Sha*/</p><p>/*#############################################################################/* /*# Bing Cai */ /*# Modify the R program from Vansteelandt and Goetghebeur*/ /*# to fit the situation that the placebo group patients have access to the treatment*/ /*#*/ /*# 1. Have two association model separately for R=1 and R=0.*/ /*# 2. Modify the H(r)*/ /*# 3. Iteration method for the selection of d and q*/ /*# 4. Modify the program for variance estimate accordingly*/ /*# / *##################################################################################*/</p><p>/*################################################################################*/ /*#y: outcome variable;*/ /*#z1: covariate(compliance) in structural model; */ /*#z2: covariate(compliance) in associational model; make sure that z1 is included lastly !!! */ /*#x: baseline covariates;*/ /*#w: weight to adjust for lost to followup;*/ /*#r: randomization indicator (1: active, 0: experimental);*/ /*#family: select error distribution and link function, eg. family=binomial(link=probit);*/ /*#psi: starting value for structural parameter, eg psi <- rep(0, ncol(Compliance));*/ /*#print: if TRUE structural parameter value in every iteration is printed;*/ /*#tol: tolerance for convergence criterion;*/ /*#robust: if TRUE robust weights are used;*/ /*#prest: estimate probability of being randomized to experimental arm (F: set this probability equal to 0.5);*/ /*#D: weight functions for structural equations (if NULL, optimal weights are estimated);*/ /*#maxiter: maximum number of allowed iterations;*/ /*#########################################################################*/</p><p>/*Before invoking %bismm(), %pre_bismm(data) must be invoked first. */ /*This step prepares the data sets being used in %bismm()*/ /*Input data must include the following variables: yobs r x z */ /*For the meanings of these variables please see notes above by Bing Cai*/ /*Output data of macro %bismm() is "out1"*/ /*02/01/2011, Daohang Sha*/ /*########################################################################*/</p><p>/*For multiple baseline covariates if they are labeled as x1, x2, x3, ...*/ /*Two things need to do,*/ /* 1) replace variable x in all proc genmod within %macro pre_bismm() with x1 x2 x3 ... */ /* 2) combine all covariates together by adding x=x1||x2||x3; right after */ /* ... */ /* use arg; */ /* read all var _all_; */ /* within proc iml in %macro bismm() */</p><p>/*09/02/2011, DS*/</p><p>%macro pre_bismm(indat);</p><p>/*add id variable to the data set*/ data data; set &indat.; id=_N_; /* drop var1;*/ keep yobs x z r id; run; data R1; set data; if R=0 then yobs=.; run; data R0; set data; if R=1 then yobs=.; run;</p><p>/* # Build association model 1: [R=1]*/ proc genmod data=R1 descending; ods output Genmod.ParameterEstimates=m2t_coef(keep=Parameter Estimate); class z(ref=first)/param=ref; model yobs = x z /dist=binomial link=logit; output out=m2t PREDICTED=pyR1 RESRAW =helput; ods exclude ModelInfo NObs ResponseProfile ClassLevels ModelFit ConvergenceStatus ParameterEstimates ; run;</p><p>/*set residual as 0 when R=0*/ data m2t; set m2t; if r=0 then helput = 0; run; /*get coefficient of model 1*/ data m2t_coef; set m2t_coef; if Parameter ne "Scale"; rename Estimate=m2t_coef; drop Parameter; run;</p><p>/* # Build association model 2 [R=0]*/ proc genmod data=R0 descending; ods output Genmod.ParameterEstimates=m2p_coef(keep=Parameter Estimate); class z(ref=first)/param=ref; model yobs = x z /dist=binomial link=logit; output out=m2p PREDICTED=pyR0 RESRAW =helpup; ods exclude ModelInfo NObs ResponseProfile ClassLevels ModelFit ConvergenceStatus ParameterEstimates ; run;</p><p>/*set residual as 0 when R=1*/ data m2p; set m2p; if r=1 then helpup = 0; run;</p><p>/*get coefficient of model 2*/ data m2p_coef; set m2p_coef; if Parameter ne "Scale"; rename Estimate=m2p_coef; drop Parameter; run;</p><p>/* # A model to predict treatment group*/ proc genmod data=data descending; model r = x/dist=binomial link=logit; output out=mr PREDICTED=mrpred resraw=r_res; ods exclude ModelInfo NObs ResponseProfile ClassLevels ModelFit ConvergenceStatus ParameterEstimates ; run;</p><p>/*put model 1 and 2 together*/ data m2tp; update m2t m2p; by id; run; data m2tpr; merge m2tp mr(keep=id mrpred r_res); by id; run; proc datasets; delete data m2p m2t m2tp mr r0 r1 pZR1 pZR0; quit; %mend;</p><p>%macro bismm(indat=ds, w=1, psi=., print="F", tol=1e-10, robust="F",prest="T", D="", maxiter=600);</p><p>/*prepare the data for estimation*/ %pre_bismm(&indat.)</p><p>/*save arguments to a data set so IML can read in*/ data arg; w=&w.; psi=&psi.; *one parameter; print=&print.; tol=&tol.; robust=&robust.; prest=&prest.; D=&D.; maxiter=&maxiter.; run;</p><p>/*start BISMM iteration estimation */ proc iml;</p><p>/*get initial arguments*/ use arg; read all var _all_;</p><p>/*for multiple baseline covariates labeled as x1, x2, and x3, DS, 09/02/2011*/ /* x=x1||x2||x3; */</p><p>/*read data set*/ use m2tpr; read all var _all_;</p><p> y=yobs; z1=z; * one parameter; z2=x||z;</p><p> use m2t_coef; read all var {m2t_coef}; use m2p_coef; read all var {m2p_coef};</p><p>/* # Function used for estimation with robust weights*/</p><p>/* ### add in intercept for z2 and x*/</p><p> ones=repeat(1,nrow(y),1); z2=ones||z2; x=ones||x;</p><p>/*one parameter*/ if psi=. then psi=repeat(0,ncol(z1),1); psiold=psi;</p><p>/* ######################### */ /* # Estimation*/ /* #########################*/</p><p>/* ###initiate q */ q=0; </p><p>/* # Fit structural model*/ do i=1 to maxiter by 1;</p><p> temp1 = z2*m2t_coef - z1*psi; temp2 = z2*m2p_coef - z1*psi; YP=r/(1+exp(-temp1)) + (1-r)/(1+exp(-temp2));</p><p> dYPdPSI = - r#exp(temp1)/((1+exp(temp1))#(1+exp(temp1)))#z1 + (1-r)#exp(temp2)/((1+exp(temp2))#(1+exp(temp2)))#z1;</p><p>YPNew = YP - dYPdPSI*psi;</p><p>/* # Calculating weight matrix */</p><p> b=inv(x`*x)*x`*dYPdPSI; zpred=x*b;</p><p> q= x*inv(x`*x)*x`*YP;</p><p> if prest="T" then do; g = ((-1)##r) # zpred/(r#mrpred+(1-r)#(1-mrpred)); end; else do; g = ((-1)##r) # zpred; end;</p><p> if (D ^= "") then do; g = D; end;</p><p> gw = g # w; gzinv= inv(t(gw)*dYPdPSI); psi = gzinv*t(gw)*(q - YPNew);</p><p>/* if (print="T") then */ /* print psi,psiold;*/</p><p>/* if (robust) */ /* {*/ /* if (ncol(z2)==ncol(g)) */ /* m2$coef<-nlm(f=glmrob, p=coef(m2), y=y, z2=z2, d=rbind(t(g)), r=r)$estimate */ /* else */ /* m2$coef<-nlm(f=glmrob, p=coef(m2), y=y, z2=z2, d=rbind(t(z2[, (1+ncol((g))):ncol(z2)]),t(g)), r=r)$estimate*/ /* }*/</p><p>YP=r/(1+exp(-temp1)) + (1-r)/(1+exp(-temp2));</p><p> dYPdPSI=-r#exp(temp1)/((1+exp(temp1))#(1+exp(temp1)))#z1 +(1-r)#exp(temp2)/((1+exp(temp2))#(1+exp(temp2)))#z1;</p><p>YPNew = YP - dYPdPSI*psi; q= x*inv(x`*x)*x`*YP; b=inv(x`*x)*x`*dYPdPSI;</p><p> zpred=x*b;</p><p> if prest="T" then do; g = ((-1)##r) # zpred/(r#mrpred+(1-r)#(1-mrpred)); end; else do; g = ((-1)##r) # zpred; end; if (D ^= "") then do; g = D; end; gw = g # w ; gzinv= inv(t(gw)*dYPdPSI); psi = (psi + gzinv*t(gw)*(q - YPNew))/2;</p><p>/*print iteration infomation*/ if (print="T") then do; iter_val=i||psi`; iter_char=char(iter_val,15,10); * convert matrix numerical element to char; col={"Iteration(i)" "psi"}; iterinfo=col//iter_char; print iterinfo; end;</p><p> tol1=t(psi-psiold)*(psi-psiold); if tol1<tol then stop; else psiold =psi;</p><p> end; *end of i do loop;</p><p> create psi var {i,psi}; append; close psi;</p><p>/* print final estamation infomation*/ if (i>=maxiter+1) then do; i=i-1; print "WARNNING: Parameter values did not converge!"; print "iteration=" i "; Total tolerance =" tol1 ">=" tol; print "Try to increase the number of max iteration: maxiter"; end; else print "Parameter values converged." "iteration=" i "; Total tolerance =" tol1 "<" tol; /* ### End OF Estimation ### */</p><p>/* ############################ */ /* # CALCULATING THE VARIANCE # */ /* ############################ */</p><p>/* #Estimated psi*/</p><p>/* #ds (INCORPORATE WEIGHT TO ADJUST FOR LOST TO FOLLOWUP)*/ d=t(g); dw=t(g*w);</p><p>/* # Build association model*/</p><p> if (robust^="T") then drob=z2; else do; if (ncol(z2)=nrow(d)) then drob=t(d); else drob=z2[,(1+ncol(t(d))):ncol(z2)]||t(d); end;</p><p>/* # Build treatment assignment model*/</p><p> u=shape(.,nrow(y),ncol(z1)+2*ncol(z2)+ncol(x)); du=shape(.,ncol(z1)+2*ncol(z2)+ncol(x),ncol(z1)+2*ncol(z2)+ncol(x));</p><p> h = r#(exp(temp1)/(1+exp(temp1))) + (1-r)#(exp(temp2)/(1+exp(temp2)));</p><p>/* ### U matrix*/</p><p> do i=1 to ncol(z1) by 1; do j=1 to nrow(z1); u[j,i]=dw[i,j]#(h[j]-q[j]); end; end;</p><p> do i=(ncol(z1)+1) to (ncol(z1)+ncol(z2)); do j=1 to nrow(z1); u[j,i]=helput[j]#drob[j,(i-ncol(z1))]; end; end;</p><p>/* ### Placebo group association part */</p><p> do i=(ncol(z1)+ncol(z2)+1) to (ncol(z1)+2*ncol(z2)); do j=1 to nrow(z1); u[j,i]=helpup[j]#drob[j,(i-ncol(z1)-ncol(z2))]; end; end;</p><p>/* # treatment assignment part */</p><p> do i=(ncol(z1)+2*ncol(z2)+1) to (ncol(z1)+2*ncol(z2)+ncol(x)); do j=1 to nrow(z1); u[j,i]=r_res[j]#x[j,(i-ncol(z1)-2*ncol(z2))]; end; end;</p><p>/* ### dU matrix*/ /* # structual part (INCORPORATE WEIGHT TO ADJUST FOR LOST TO FOLLOWUP) */</p><p> do i=1 to ncol(z1); do j=1 to ncol(z1); du[i,j]=-sum(r#exp(temp1)/((1+exp(temp1))#(1+exp(temp1)))#dw[i,]`#z1[,j] +(1-r)#exp(temp2)/ ((1+exp(temp2))#(1+exp(temp2)))#dw[i,]`#z1[,j])/nrow(y); end;</p><p> do j=(ncol(z1)+1) to (ncol(z1)+ncol(z2)); du[i,j]=sum(r#exp(temp1)/((1+exp(temp1))#(1+exp(temp1)))#dw[i,]`#z2[,(j- ncol(z1))])/nrow(y); end; </p><p> do j=(ncol(z1)+ncol(z2)+1) to (ncol(z1)+2*ncol(z2)); du[i,j]=sum((1-r)#exp(temp2)/((1+exp(temp2))#(1+exp(temp2)))#dw[i,]`#z2[,(j-ncol(z1)- ncol(z2))])/nrow(y); end;</p><p> do j=(ncol(z1)+2*ncol(z2)+1) to (ncol(z1)+2*ncol(z2)+ncol(x)); du[i,j]=-sum((dw[i,]`/(r#(1-mrpred)+(1-r)#mrpred)##2)#(h-q)#(2*r-1)#mrpred#(1- mrpred)#x[,(j-ncol(z1)-2*ncol(z2))])/nrow(y); end; end;</p><p>/* # association part */</p><p> do i=(1+ncol(z1)) to (ncol(z1)+ncol(z2)); do j=1 to ncol(z1); du[i,j]=0; end; do j=(1+ncol(z1)) to (ncol(z1)+ncol(z2)); du[i,j]=-sum(pyR1#(1-pyR1)#r#drob[,(i-ncol(z1))]#z2[,(j-ncol(z1))])/nrow(y)*2; end; do j=(1+ncol(z1)+ncol(z2)) to (ncol(z1)+2*ncol(z2)); du[i,j]=0; end; do j=(1+ncol(z1)+2*ncol(z2)) to (ncol(z1)+2*ncol(z2)+ncol(x)); du[i,j]=0; end; end;</p><p> do i=(1+ncol(z1)+ncol(z2)) to (ncol(z1)+2*ncol(z2)); do j=1 to (ncol(z1)+ncol(z2)); du[i,j]=0; end; do j=(1+ncol(z1)+ncol(z2)) to (ncol(z1)+2*ncol(z2)); du[i,j]=-sum(pyR0#(1-pyR0)#r#drob[,(i-ncol(z1)-ncol(z2))]#z2[,(j-ncol(z1)- ncol(z2))])/nrow(y)*2; end; do j=(1+ncol(z1)+2*ncol(z2)) to (ncol(z1)+2*ncol(z2)+ncol(x)); du[i,j]=0; end; end;</p><p>/* # treatment assignment part */</p><p> do i=(1+ncol(z1)+2*ncol(z2)) to (ncol(z1)+2*ncol(z2)+ncol(x)); do j=1 to ncol(z1); du[i,j]=0; end; do j=(1+ncol(z1)) to (ncol(z1)+2*ncol(z2)); du[i,j]=0; end; do j=(1+ncol(z1)+2*ncol(z2)) to (ncol(z1)+2*ncol(z2)+ncol(x)); du[i,j]=-sum(mrpred#(1-mrpred)#x[,(j-ncol(z1)-2*ncol(z2))]#x[,(i-ncol(z1)- 2*ncol(z2))])/nrow(y); end; end;</p><p> if prest="T" then do; idu=inv(du); end; else do; idu=inv(du[1:(ncol(z1)+ncol(z2)),1:(ncol(z1)+ncol(z2))]); u=u[,1:(ncol(z1)+ncol(z2))]; end;</p><p>/* # variance matrix*/ vari=idu*(u`*u)*idu`/nrow(y)**2;</p><p> if (print="T") then do; print "rvariance:", vari; end;</p><p>/*print model m2t outputs*/</p><p>/* # Print association model1*/ /* # cat("\n Association model1: \n\n")*/ /* # Print structural model*/</p><p> covmat= vari[1:nrow(psi),1:nrow(psi)]; var_cf=diag(covmat);</p><p>/* TTH: need to account for two element vectors psi, s_err, zvalue, pvalue, lowlimit, uplimit */ ones=repeat(1,ncol(var_cf),1); var=var_cf*ones; s_err=sqrt(var); zvalue=psi/s_err; pvalue=2*(1-cdf("normal",abs(zvalue))); lowlimit=psi-1.96*s_err; uplimit=psi+1.96*s_err;</p><p>/*prepare for print out */ if (print="T") then do; val=psi||var||s_err||lowlimit||uplimit||pvalue; print val; cha=char(val,8,5); * convert matrix numerical element to char; col={"psi" "var" "SE" "LowerCI" "UpperCI" "p value"}; paraEstimate=col//cha; print paraEstimate; end;</p><p> create out1 var {psi, var, lowlimit, uplimit}; append; /* show contents;*/ close out1; quit; %mend; </p>
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages11 Page
-
File Size-