Appendix: Sample SAS codes for PMM Approximation and Bayesian Analysis
Assume the dataset “InDat” contain variables: patient (patient id), therapy (treatment code: DRUG or PLACEBO), basval (baseline value), y1, y2, y3, and y4 (repeated measures after baseline). Assume monotone missing and no missing for y1.
**** PMM Approximation using mixed model estimates ****;
datalda; *** longitudinal data for MMRM mixed model ***;
setInDat;
arrayyy{4} y1 y2 y3 y4;
do time=1to4;
y=yy{time};
output;
end;
drop y1 – y4;
run;
dataforMCMC; *** dataset for Bayesian MCMC analysis ***;
setInDat end=eof;
retainntrt0 np1 0 np2 0 np3 0;
*total subjects in Drug, and numbers of missing in patterns 1, 2, 3 *;
trt=(therapy='DRUG');
iftrt=1thendo;
ntrt=ntrt+1;
if y2=.thendo; np1=np1+1; end; ** missing pattern 1 **;
elseif y3=.thendo; np2=np2+1; end; ** pattern 2 **;
elseif y4=.thendo; np3=np3+1; end; ** pattern 3 **;
end;
ifeofthendo;
mp1=round(np1/ntrt,.00000001); ** missing proportion in pattern 1 **;
mp2=round(np2/ntrt,.00000001); ** missing proportion in pattern 2 **;
mp3=round(np3/ntrt,.00000001); ** missing proportion in pattern 3 **;
mp4=1-mp1-mp2-mp3; ** proportion of completers **;
callsymput('ntrt', ntrt); *** sample size in Drug ***;
callsymput('mp1', mp1);
callsymput('mp2', mp2);
callsymput('mp3', mp3);
callsymput('mp4', mp4);
end;
keep patient basval y1 y2 y3 y4trt;
run;
**** Primary analysis using MMRM mixed model ****;
**** Coding for Therapy: Drug should be ordered before Placebo ****;
procmixeddata=lda;
class therapy time;
model y=basval*time therapy*time / nointscovbddfm=kr;
estimate"MAR" therapy*time 0001 000 -1;
lsmeans therapy*time / ecov;
repeated time / subject=patient type=un r=1;
** assume first subject is a completer, otherwise change “r=” option
to a patient of completer so the covariance matrix can be outputed **;
odsoutputlsmeans=lsmR=covestimates=mix;
title"MMRM analysis with mixed model";
run;
**** PMM approximation for CIR, CR, and JR ****;
prociml;
c_mar = {0001 000 -1}; * MAR analysis at last time point *;
c_jr = {000 &mp4 000 -&mp4}; * JR analysis at last time point *;
c_cir = {&mp1 &mp2 &mp3 &mp4 -&mp1 -&mp2 -&mp3 -&mp4}; * for CIR *;
usecov; read all var {col1 col2 col3 col4} into v;
uselsm; read all var{estimate} into beta;
uselsm;read all var{cov1 cov2 cov3 cov4 cov5 cov6 cov7 cov8}into w;
v_mar = (c_mar)*w*T(c_mar);
out=(c_mar*beta)||sqrt(v_mar); *** Mixed model estimate and SE ***;
v_Jr = (c_jr)*w*T(c_jr) + &mp4*(1-&mp4)*(beta[8]-beta[4])**2/&ntrt;
*** combined variance for JR, ntrt=sample size in Drug group ***;
out=out//( (c_jr*beta)||sqrt(v_jr) ); ** JR estimate and SE **;
ww=(c_cir[1:4])*T(c_cir[1:4]);
ww=diag(c_cir[1:4]) - ww;
diff = beta[1:4] - beta[5:8];
v_cir = (c_cir)*w*T(c_cir) + T(diff)*ww*diff/&ntrt;
*** combined variance for CIR, ntrt= sample size in Drug group ***;
out=out//( (c_cir*beta)||sqrt(v_cir) ); ** CIR estimate and SE **;
mp1=&mp1*v[4,1]/v[1,1] + &mp2*(v[4,1:2]*inv(V[1:2,1:2]))[1] +
&mp3*(v[4,1:3]*inv(V[1:3,1:3]))[1];
mp2=&mp2*(v[4,1:2]*inv(V[1:2,1:2]))[2] +
&mp3*(v[4,1:3]*inv(V[1:3,1:3]))[2];
mp3=&mp3*(v[4,1:3]*inv(V[1:3,1:3]))[3];
c_cr=(mp1)||(mp2)||(mp3)||{&mp4};
c_cr = c_cr||(-c_cr);
diff=( (v[4,1]/v[1,1])#beta[1]//
((v[4,1:2]*inv(V[1:2,1:2]))*beta[1:2])//
((v[4,1:3]*inv(V[1:3,1:3]))*beta[1:3])//beta[4] ) -
( (v[4,1]/v[1,1])#beta[5]//
((v[4,1:2]*inv(V[1:2,1:2]))*beta[5:6])//
((v[4,1:3]*inv(V[1:3,1:3]))*beta[5:7])//beta[8] );
v_cr = c_cr*w*T(c_cr) + T(diff)*ww*diff/&ntrt;
out=out//( (c_cr*beta)||sqrt(v_cr) );
out = {1,2,3,4}||out;
create sum1 from out[colname={'Code''estimate''Se'}]; appendfrom out;
quit;
dataoutall; set sum1;
if code=1then Method='MAR_MMRM ';
elseif code=2then Method='JR_Apprx ';
elseif code=3then Method='CIR_Apprx ';
elseif code=4then Method='CR_Apprx ';
drop code;
run;
**** Bayesian Analysis with MCMC ****;
data_null_; set mix;
callsymput('mixDF', df);
*** get DF from MMRM mixed model analysis ***;
*** get Dirichlet posterior parameters using Geofrey's prior ***;
nn1=&ntrt*&mp1+0.5;
nn2=&ntrt*&mp2+0.5;
nn3=&ntrt*&mp3+0.5;
nn4=&ntrt*&mp4+0.5;
callsymput('nn1', nn1);
callsymput('nn2', nn2);
callsymput('nn3', nn3);
callsymput('nn4', nn4);
run;
*** Bayesian approach ***;
odshtml;
odsgraphics;
ProcMCMCdata=forMCMCnbi=2000ntu=2000nmc=200000seed=7892354thin=10propcov=CONGRA diag=allplots(smooth)=allmonitor=(MAR_MCMC CR__MCMC JR__MCMC CIR_MCMC);
arrayyy{4} y1 y2 y3 y4;
array mu{4} mu1 - mu4;
arraymp[4] mp1 - mp4;
arraynn[4] (&nn1 &nn2 &nn3 &nn4);
arraymup{4} mup1-mup4; *** mean for placebo ***;
arraymut{4} mut1-mut4; *** mean for test drug ***;
array beta[4] beta1-beta4; *** slope for baseline over time ***;
arraycov[4,4];
arraycov_a[3,3]; *** sub matrix for lower dimension ***;
arraycov_b[2,2];
arraybcov_a[1,3]; *** sub vector for cov of y4 with y1-y3 ***;
arraybcov_b[1,2];
arrayiv_a[3,3]; *** inverse matrix for cov_a ***;
arrayiv_b[2,2];
arraybiv_a[1,3]; *** bcov_a*iv_a ***;
arraybiv_b[1,2];
arraymtp_a[3]; *** subvector for mut - mup ***;
arraymtp_b[2];
array bmu3[1]; *** biv_a*mtp_a = bcov_a*inv(cov_a)*(mut-mup) ***;
array bmu2[1];
array s0[4,4] (1000 0100 0010 0001);
BEGINNODATA;
MAR_MCMC = mut4-mup4; *** mean difference at time 4 under MAR ***;
doi=1to3; mtp_a[i]=mut[i]-mup[i]; bcov_a[1,i]=cov[4,i];
do j=1to3; cov_a[i,j]=cov[i,j]; end;
end;
doi=1to2; mtp_b[i]=mut[i]-mup[i]; bcov_b[1,i]=cov[4,i];
do j=1to2; cov_b[i,j]=cov[i,j]; end;
end;
callinv(cov_a,iv_a);
callmult(bcov_a, iv_a, biv_a);
callmult(biv_a, mtp_a, bmu3);
callinv(cov_b,iv_b);
callmult(bcov_b, iv_b, biv_b);
callmult(biv_b, mtp_b, bmu2);
bmu1 = cov[1,4]*(mut1-mup1)/cov[1,1];
CR__MCMC = (mp4*(mut4-mup4) + mp3* bmu3[1]
+ mp2* bmu2[1] + mp1* bmu1); *** copy reference ***;
JR__MCMC = mp4*(mut4-mup4); *** jump to reference ***;
CIR_MCMC = (mp4*(mut4-mup4) + mp3* (mut3-mup3)
+ mp2*(mut2-mup2) + mp1*(mut1-mup1)); *** CIR ***;
ENDNODATA;
*** initial values ***;
parms mup1 -1.6 mup2 -4.5 mup3 -6.1 mup4 -7.1
mut1 -2.0 mut2 -5.5 mut3 -8.0 mut4 -9.6;
parms beta1 -1. beta2 -1. beta3 -1.0 beta4 -1.4;
parmscov;
parmsmp {&mp1 &mp2 &mp3 &mp4};
priormp ~ dirich(nn);
priormup: mut: beta: ~ normal(0, var=10000);
priorcov ~ iwish(4,S0);
do i = 1to4;
mu[i] = mup[i]*(1-trt)+mut[i]*trt + beta[i]*basval;
end;
modelyy ~ mvn(mu, cov);
title"Bayesian MCMC analysis";
odsoutputPostSumInt=sum2;
run;
**** Combine results and use DF from mixed model ****;
dataoutall;
setoutall
sum2(rename=(mean=Estimate stddev=se parameter=Method)
drop=N HPDLowerHPDUpper);
DF = &mixDF;
probt=2-2*probt(abs(estimate/se), df);
LCL = estimate - tinv(0.975, DF)*se;
UCL = estimate + tinv(0.975, DF)*se;
run;
odslisting;
procprintdata=outall;
var Method estimate se probt LCL UCL;
title"Summary of Analysis Results";
run;
1