Appendix V: the SAS Macro Bismm

Appendix V: the SAS Macro Bismm

<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>

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    11 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us