Greetings.
I have had success learning and implementing procedures from SAS papers. I am for the first time incorporating a macro for bootstrapping. I am trying to implement the macros in appendix II and III in SAS paper 2424-2018. It was a straight forward cut-and-paste. When I run the program, it prints to the log and output windows with each iteration. But, the final html output is suppressed until the last iteration. However, it only prints the results of the last macro, not the first one. The macros include all the correct things to suppress the output that I have been reading. I have been search Google so long it keeps asking me to verify that I am not a bot. I am not a sophisticated user so I may not even be understanding that I seen the correct answer. Below is my code that includes some of the suggestions that I have seen. The suggestions do suppress log and output windows for the main statistical procedure but not the iterations for the macro. I have 10 iterations so that I can run and try different things to fix this error. I have tried to location of the macro call before and after the macro program itself, not sure if that is an issue. I am using version 9.1 on windows in a dual boot Mac.
OPTIONS LS=120 PS=80;
options nosource nonotes;
ods listing close;
ods html;
Data D1;
INPUT ID visit x y;
DATALINES;
1.0000000e+00 1.0000000e+00 4.1466014e+01 1.5499570e+01
1.0000000e+00 2.0000000e+00 8.2491390e+01 1.6625374e+01
1.0000000e+00 3.0000000e+00 1.1112596e+02 1.7012588e+01
1.0000000e+00 4.0000000e+00 1.5296788e+02 2.0967996e+01
1.0000000e+00 5.0000000e+00 1.5126439e+02 2.0436103e+01
2.0000000e+00 1.0000000e+00 3.6634545e+01 1.4955640e+01
2.0000000e+00 2.0000000e+00 7.2975351e+01 1.6796694e+01
2.0000000e+00 3.0000000e+00 1.0506238e+02 2.3160999e+01
2.0000000e+00 4.0000000e+00 1.3483964e+02 2.1714623e+01
2.0000000e+00 5.0000000e+00 1.4373045e+02 1.5103717e+01
.......
4.8000000e+01 1.0000000e+00 4.8610660e+01 1.3193223e+01
4.8000000e+01 2.0000000e+00 9.5623122e+01 1.5189560e+01
4.8000000e+01 3.0000000e+00 1.3864495e+02 1.8091522e+01
4.8000000e+01 4.0000000e+00 1.8578662e+02 2.0179639e+01
4.8000000e+01 5.0000000e+00 2.5081385e+02 2.1945149e+01
;
data data_long (drop=x y i);
set D1 (keep=ID visit x y);
array var[2] x y;
do i =1 to 2;
vtype =i;
response = var[i];
output;
end;
run;
quit;
title 'Hamlet Paper 198-29';
proc mixed data=data_long method=ml;
class ID vtype visit;
model response = vtype / solution ddfm=kr;
random vtype / type=un subject=ID v vcorr;
repeated vtype / type=un subject=visit(ID);
*repeated vtype visit/ type=un@ar(1) subject=ID r rcorr;
*repeated vtype visit/ type=un@cs subject=ID r rcorr;
run;
quit;
%MMCorr_BSpvalue(data=D1,ID=ID,rep=visit,var1=x,var2=y,numSamples=10);
%MMCorr_BSCI(data=D1, ID=ID, rep=visit, var1=x, var2=y, numSamples=10);
%macro MMCorr_BSCI(data=,ID=,rep=,var1=,var2=,numSamples=);
/*Select bootstrap samples*/
options nosource nonotes;
ods listing close;
proc sort data=&data.(keep=&ID.) out=&data._ID nodupkey;
by &ID.;
run;
proc surveyselect data=&data._ID NOPRINT seed=864132
out=&data._boot(drop=NumberHits)
method=urs samprate=1 OUTHITS reps=&NumSamples.;
run;
data &data._boot;
set &data._boot;
if first.&ID. then RptNum = 1;
else RptNum + 1;
by Replicate &ID.;
ID2 = &ID. || "_" || strip(RptNum);
run;
data &data._boot;
set &data._boot;
if first.Replicate then SubjNum = 1;
else SubjNum + 1;
by Replicate;
run;
data results;
input Replicate rho12 convstatus reason $200. rho1 rho2;
run;
/*Bootstrap: Sample Individuals*/
%do j=1 %to &NumSamples.;
proc sql;
create table bootsamp
as select a.*,b.&rep.,b.&var1.,b.&var2.
from &data._boot a
left join &data. b
on &data._boot.ID = &data..ID
where Replicate = &j.;
quit;
proc sort data=bootsamp;
by &ID. RptNum &rep.;
run;
data &data._long (drop=&var1. &var2. i); *univariate format;
set bootsamp (keep=&ID. RptNum ID2 &rep. &var1. &var2.);
if first.ID2 then Visit2 = 1;
else Visit2 + 1;
by ID2;
array var[2] &var1. &var2.;
do i = 1 to 2;
Vtype = i;
Response = var[i];
output;
end;
run;
/*Fit Hamlett (2004) mixed model for bootstrap sample*/
proc mixed data=&data._long method=ml;
class ID2 vtype visit2;
model response = vtype / solution ddfm=kr;
random vtype / type=un subject=ID2 v vcorr;
repeated vtype / type=un subject=visit2(ID2);
ods output VCorr=VCorr ConvergenceStatus=CS;
run;
/*Calculate correlation*/
proc iml;
use Vcorr(keep=COL:);
read all var _ALL_ into Vcorr;
close Vcorr;
use CS;
read all var {Status} into convstatus;
read all var {Reason} into reason;
close CS;
R = Vcorr[1:2,1:2];
v = cusum( 1 || (ncol(R):2) );
rho = remove(vech(R), v);
Replicate = j(2*(2-1)/2,1,&j.);
create corrcalc var {Replicate rho convstatus reason};
append;
close corrcalc;
quit;
data results;
set results corrcalc;
run;
dm "output;clear;log;clear;odsresults;select all;clear;";
%end;
data results2;
set results;
where convstatus = 0;
run;
data &data._long (drop=&var1. &var2. i); *univariate format;
set &data. (keep=&ID. &rep. &var1. &var2.);
array var[2] &var1. &var2.;
do i = 1 to 2;
Vtype = i;
Response = var[i];
output;
end;
run;
/*Fit Hamlett (2004) mixed model for original dataset*/
proc mixed data=&data._long method=ml covtest asycov asycorr;
class &ID. vtype &rep.;
model response = vtype / solution ddfm=kr;
random vtype / type=un subject=&ID. v vcorr;
repeated vtype / type=un subject=&rep.(&ID.);
ods output CovParms=CovParms;
run;
proc iml;
use results2;
read all var {rho} into rho;
close results2;
numsamp = nrow(rho);
use Covparms;
read all var {Estimate} into Cov_estimate;
close Covparms;
a = Cov_estimate[1];
b = Cov_estimate[2];
c = Cov_estimate[3];
g = Cov_estimate[4];
h = Cov_estimate[5];
i = Cov_estimate[6];
rhohat = (b+h)/sqrt((a+g)*(c+i));
BS_mean = mean(rho);
z = quantile("Normal",mean(rho < rhohat));
a = 0;
qlb = cdf("Normal",z+((z+quantile("Normal",0.025))/(1-a*(z+quantile("Normal",0.025)))));
qub = cdf("Normal",z+((z+quantile("Normal",0.975))/(1-a*(z+quantile("Normal",0.975)))));
call qntl(lb,rho,qlb);
call qntl(ub,rho,qub);
BootstrapOutput = j(1,4,.);
BootstrapOutput[,1]=rhohat;
BootstrapOutput[,2]=BS_mean;
BootstrapOutput[,3]=lb;
BootstrapOutput[,4]=ub;
Outtitle={'Estimate' 'Bootstrap Estimate' '95% CI Lower Bound' '95% CI Upper Bound'};
Varnames=t("&var1. and &var2.");
PRINT BootstrapOutput[colname=Outtitle rowname=Varnames];
quit;
%mend MMCorr_BSCI;
%macro MMCorr_BSpvalue(data=,ID=,rep=,var1=,var2=,numSamples=);
/*Select bootstrap samples*/
proc sort data=&data.(keep=&ID.) out=&data._ID nodupkey;
by &ID.;
run;
proc surveyselect data=&data._ID NOPRINT seed=864132
out=&data._boot(drop=NumberHits)
method=urs samprate=1 OUTHITS reps=&NumSamples.;
run;
data &data._boot;
set &data._boot;
if first.&ID. then RptNum = 1;
else RptNum + 1;
by Replicate &ID.;
ID2 = &ID. || "_" || strip(RptNum);
run;
data &data._boot;
set &data._boot;
if first.Replicate then SubjNum = 1;
else SubjNum + 1;
by Replicate;
run;
data results;
input Replicate rho convstatus reason $200.;
run;
/*Bootstrap: Sample Individuals*/
%do j=1 %to &NumSamples.;
proc sql;
create table bootsamp
as select a.*,b.&rep.,b.&var1.,b.&var2.
from &data._boot a
left join &data. b
on &data._boot.ID = &data..ID
where Replicate = &j.;
quit;
proc sort data=bootsamp;
by &ID. RptNum &rep.;
run;
/*shuffle Wi's within subject, rematch with Ui's form m_i new pairs*/
data w_order;
set bootsamp (keep=ID2 SubjNum &rep. &var2.);
order = ranuni(0);
run;
proc sort data=w_order;
by ID2 order;
run;
/*create line number variable and merge on the line number*/
data bootsamp;
set bootsamp(drop=&var2.);
linenum = _n_;
run;
data w_order;
set w_order(keep=&var2.);
linenum = _n_;
run;
data bootsamp;
merge bootsamp w_order;
by linenum;
run;
data &data._long (drop=&var1. &var2. i); *univariate format;
set bootsamp (keep=&ID. RptNum ID2 &rep. &var1. &var2.);
if first.ID2 then Visit2 = 1;
else Visit2 + 1;
by ID2;
array var[2] &var1. &var2.;
do i = 1 to 2;
Vtype = i;
Response = var[i];
output;
end;
run;
/*Fit Hamlett (2004) mixed model for bootstrap sample*/
proc mixed data=&data._long method=ml;
class ID2 vtype visit2;
model response = vtype / solution ddfm=kr;
random vtype / type=un subject=ID2 v vcorr;
repeated vtype / type=un subject=visit2(ID2);
ods output VCorr=VCorr ConvergenceStatus=CS V=V SolutionF=SolutionF;
run;
/*Calculate correlation for each bootstrap sample*/
proc iml;
use Vcorr(keep=COL:);
read all var _ALL_ into Vcorr;
close Vcorr;
use V(keep=COL:);
read all var _ALL_ into VCov;
close V;
use CS;
read all var {Status} into convstatus;
read all var {Reason} into reason;
close CS;
use SolutionF;
read all var {Estimate} into mu;
close SolutionF;
R = Vcorr[1:2,1:2];
v = cusum( 1 || (ncol(R):2) );
rho = remove(vech(R), v);
Replicate = j(2*(2-1)/2,1,&j.);
create corrcalc var {Replicate rho convstatus reason};
append;
close corrcalc;
quit;
data results;
set results corrcalc;
run;
dm "output;clear;log;clear;odsresults;select all;clear;";
%end;
data results2;
set results;
where convstatus = 0;
run;
data &data._long (drop=&var1. &var2. i); *univariate format;
set &data. (keep=&ID. &rep. &var1. &var2.);
array var[2] &var1. &var2.;
do i = 1 to 2;
Vtype = i;
Response = var[i];
output;
end;
run;
/*Fit Hamlett (2004) mixed model for original dataset*/
proc mixed data=&data._long method=ml covtest asycov asycorr;
class &ID. vtype &rep.;
model response = vtype / solution ddfm=kr;
random vtype / type=un subject=&ID. v vcorr;
repeated vtype / type=un subject=&rep.(&ID.);
ods output CovParms=CovParms;
run;
/*Calculate p-value*/
proc iml;
use results2;
read all var {rho} into rho;
close results2;
BS_mean = mean(rho);
numsamp = nrow(rho);
use Covparms;
read all var {Estimate} into Cov_estimate;
close Covparms;
a = Cov_estimate[1];
b = Cov_estimate[2];
c = Cov_estimate[3];
g = Cov_estimate[4];
h = Cov_estimate[5];
i = Cov_estimate[6];
rhohat = (b+h)/sqrt((a+g)*(c+i));
if rhohat >0 then p = (sum(rho < 0)+sum(rho > 2*rhohat))/numsamp;
else p = (sum(rho > 0)+sum(rho < 2*rhohat))/numsamp;
BootstrapOutput = j(1,3,.);
BootstrapOutput[,1]=rhohat;
BootstrapOutput[,2]=BS_mean;
BootstrapOutput[,3]=p;
Outtitle={'Estimate' 'Bootstrap Estimate' 'Pvalue'};
Varnames=t("&var1. and &var2.");
PRINT BootstrapOutput[colname=Outtitle rowname=Varnames];
quit;
%mend MMCorr_BSpvalue;
Thank you. I will give it a try.
dg
I have tried many suggestions including turning off ODS. Printing to the log and output windows are now surpassed. Now, what whatever macros is the last one to run, those are the only results to finally be printed. The results from the previous macro is erased. I contacted the author and was told to rename the last output differently, i.e., bootstrapoutput2. Then go back to the SAS data set and find both outputs. Still only one exists.
dg
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Select SAS Training centers are offering in-person courses. View upcoming courses for: