Dear SAS Gurus,
please help me debugging my loop.
%let k_interims = 5; %let n_1 = 100; %let n_2 = 100; %let n_3 = 100; %let n_4 = 100; %let n_5 = 100; %let i_nullprop_mean = 0.5; %let i_nullprop_SD = 0.1; %let j_alternative_mean = 0.5; %let j_alternative_SD = 0.1; data _null_; do i=1 to &k_interims by 1; s= ' data count_'||trim(left(put(i,3.)))||' (drop=j); length trt sbi 4; if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do; do j = 1 to round(&n_'||trim(left(put(i,3.)))||', 2) by 1; if mod(j, 2) eq 0 then do; trt = 1; sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); end; else do; trt = 0; sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); end; output; end; end; else if '||trim(left(put(i,3.)))||' ne "1" or '||trim(left(put(i,3.)))||' ne 1 then do; set count_'||trim(left(put(i-1, 3.)))||'; do j = 1 to round(&n_'||trim(left(put(i,3.)))||', 2) by 1; if mod(j, 2) eq 0 then do; trt = 1; sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); end; else do; trt = 0; sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); end; output; end; end; run; '; call execute(s); end; run;
results in right at the first if statement for the case that i=1:
ERROR: File WORK.COUNT_0.DATA does not exist.
I don't understand why SAS does not accept the case:
if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do;
As you can see I tried to resolve by handling i as a character.
In python I would simply put a:
print(i)
in between the loop.
How is it possible to debug such cases?
THX and BR
Lukas
Making a 1001 assumptions here, I think one of these two programs is closer to what you're looking for - likely the second.
%let k_interims = 5;
%let n_1 = 10;
%let n_2 = 10;
%let n_3 = 10;
%let n_4 = 10;
%let n_5 = 10;
%let i_nullprop_mean = 0.5;
%let i_nullprop_SD = 0.1;
%let j_alternative_mean = 0.5;
%let j_alternative_SD = 0.1;
proc datasets lib=work;
delete count_:;
run;quit;
options mprint symbolgen;
*expand dataset exponentially;
%macro loop (n=);
%do i=1 %to &n;
data count_&i.;
length trt sbi 4;
%if &i ne 1 %then
%do;
set count_%eval(&i-1);
%end;
do j=1 to &&n_&i;
if mod(j, 2) eq 0 then
do;
trt=1;
sbi=rand("Bernoulli", abs(rand("Normal", &j_alternative_mean,
&j_alternative_SD)));
end;
else
do;
trt=0;
sbi=rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean,
&i_nullprop_SD)));
end;
output;
end;
run;
%end;
%mend;
%loop(n=&k_interims);
Appends data sets together;
proc datasets lib=work;
delete count_:;
run;quit;
*appends each dataset together at the end for the last dataset to have 50 rows;
%macro loop (n=);
%do i=1 %to &n;
data count_&i.;
length trt sbi 4;
do j=1 to &&n_&i;
if mod(j, 2) eq 0 then
do;
trt=1;
sbi=rand("Bernoulli", abs(rand("Normal", &j_alternative_mean,
&j_alternative_SD)));
end;
else
do;
trt=0;
sbi=rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean,
&i_nullprop_SD)));
end;
output;
end;
run;
%if &i ne 1 %then
%do;
proc append base=count_&i data=count_%eval(&i-1);
run;
%end;
%end;
%mend;
%loop(n=&k_interims);
@LuGa wrote:
Dear SAS Gurus,
please help me debugging my loop.
%let k_interims = 5; %let n_1 = 100; %let n_2 = 100; %let n_3 = 100; %let n_4 = 100; %let n_5 = 100; %let i_nullprop_mean = 0.5; %let i_nullprop_SD = 0.1; %let j_alternative_mean = 0.5; %let j_alternative_SD = 0.1; data _null_; do i=1 to &k_interims by 1; s= ' data count_'||trim(left(put(i,3.)))||' (drop=j); length trt sbi 4; if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do; do j = 1 to round(&n_'||trim(left(put(i,3.)))||', 2) by 1; if mod(j, 2) eq 0 then do; trt = 1; sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); end; else do; trt = 0; sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); end; output; end; end; else if '||trim(left(put(i,3.)))||' ne "1" or '||trim(left(put(i,3.)))||' ne 1 then do; set count_'||trim(left(put(i-1, 3.)))||'; do j = 1 to round(&n_'||trim(left(put(i,3.)))||', 2) by 1; if mod(j, 2) eq 0 then do; trt = 1; sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); end; else do; trt = 0; sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); end; output; end; end; run; '; call execute(s); end; run;results in right at the first if statement for the case that i=1:
ERROR: File WORK.COUNT_0.DATA does not exist.
I don't understand why SAS does not accept the case:
if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do;
As you can see I tried to resolve by handling i as a character.
In python I would simply put a:
print(i)in between the loop.
How is it possible to debug such cases?
THX and BR
Lukas
Look at macros as code generators.
Your macro generates syntactically wrong code like:
data _null_;
data count_0;
.....
run;
run;
Without doing much digging into your code it looks to me like your mixing macro level and data step level code in a way that's not possible. I've also got some suspicion that you wouldn't need any macro logic at all but could keep things simple using data step only.
I suggest you tell us what you have and what you want to achieve.
Hi Patrick,
thanks for your help.
I would like to create data sets sequentially. (Data2 += Data1; Data3 += Data2 ..... DataK += DataJ)
2 groups (treatment and placebo) and a bernoulli distributed outcome variable (SBI).
Thanks in advance and best regards
Lukas
@LuGa wrote:
Hi Patrick,
thanks for your help.
I would like to create data sets sequentially. (Data2 += Data1; Data3 += Data2 ..... DataK += DataJ)
2 groups (treatment and placebo) and a bernoulli distributed outcome variable (SBI).
Thanks in advance and best regards
Lukas
Make a small example of Data 1. Then show us what Data 2 is supposed to look like. I am afraid that this
Data2 += Data1; Data3 += Data2 ..... DataK += DataJ) looks like Data2 is supposed to be the same as Data1 as that "+" has no meaning in context that makes sense.
Note that the basic code you need to create a new data set from an existing one is:
data data2; set data1; run;
Plus, why do you think that you need multiple data sets???
You are going to a lot of effort apparently to force even/odd assignment to treatment. Why? What analysis are you doing that requires such? Typically if you want 50 in one group and 50 in another group you might do something like:
do j = 1 to 50; do trt=0 to 1; if trt = 1 then sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); else if trt = 0 then sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); output; end; end;
Have you tested a very small attempt to use SET inside a loop as you attempt? You might find the results a little different than you expect (not that I actually follow the intent
I suspect that one data set with a variable indicating which "run", probably more correctly referred to as a REPLICATE, that would be equivalent to the numeral in your data set names, would be more understandable. Plus there are procedures that use Replicate for analysis.
What is it that you are trying to do?
Your data _null_ step is completely unreadable. If I try to convert it into something I can read
data _null_;
do i=1 to &k_interims by 1;
s= 'data count_'
||trim(left(put(i,3.)))
||' (drop=j);length trt sbi 4;if '
||trim(left(put(i,3.)))
||' eq "1" or '
||trim(left(put(i,3.)))
||' eq 1 then do;do j = 1 to round(&n_'
||trim(left(put(i,3.)))
||', 2) by 1;if mod(j, 2) eq 0 then do;trt = 1;'
||'sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD)));'
||'end;else do;trt = 0;sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD)));'
||'end;output;end;end;else if '
||trim(left(put(i,3.)))
||' ne "1" or '
||trim(left(put(i,3.)))
||' ne 1 then do;set count_'
||trim(left(put(i-1, 3.)))
||';do j = 1 to round(&n_'
||trim(left(put(i,3.)))
||', 2) by 1;if mod(j, 2) eq 0 then do;trt = 1;'
||'sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD)));'
||'end;else do;trt = 0;sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD)));'
||'end;output;end;end;run;';
call execute(s);
end;
run;
It still makes no sense to me.
Is the goal to write a PROGRAM? Why not just write the program to a file? Then you can LOOK at the file and see if the generated program makes any sense. Also then you can use the power of the PUT statement to make writing the code easier.
filename code temp;
data _null_;
file code ;
do i=1 to &k_interims by 1;
put 'data count_' i '(drop=j);'
/ ' length trt sbi 4;'
....
Some of that logic makes no sense. For example this block:
'if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do;'
Did you mean to run the IF in the data _NULL_ step? Do you want to generate different code when I=1 then for the other times through the DO loop?
Making a 1001 assumptions here, I think one of these two programs is closer to what you're looking for - likely the second.
%let k_interims = 5;
%let n_1 = 10;
%let n_2 = 10;
%let n_3 = 10;
%let n_4 = 10;
%let n_5 = 10;
%let i_nullprop_mean = 0.5;
%let i_nullprop_SD = 0.1;
%let j_alternative_mean = 0.5;
%let j_alternative_SD = 0.1;
proc datasets lib=work;
delete count_:;
run;quit;
options mprint symbolgen;
*expand dataset exponentially;
%macro loop (n=);
%do i=1 %to &n;
data count_&i.;
length trt sbi 4;
%if &i ne 1 %then
%do;
set count_%eval(&i-1);
%end;
do j=1 to &&n_&i;
if mod(j, 2) eq 0 then
do;
trt=1;
sbi=rand("Bernoulli", abs(rand("Normal", &j_alternative_mean,
&j_alternative_SD)));
end;
else
do;
trt=0;
sbi=rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean,
&i_nullprop_SD)));
end;
output;
end;
run;
%end;
%mend;
%loop(n=&k_interims);
Appends data sets together;
proc datasets lib=work;
delete count_:;
run;quit;
*appends each dataset together at the end for the last dataset to have 50 rows;
%macro loop (n=);
%do i=1 %to &n;
data count_&i.;
length trt sbi 4;
do j=1 to &&n_&i;
if mod(j, 2) eq 0 then
do;
trt=1;
sbi=rand("Bernoulli", abs(rand("Normal", &j_alternative_mean,
&j_alternative_SD)));
end;
else
do;
trt=0;
sbi=rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean,
&i_nullprop_SD)));
end;
output;
end;
run;
%if &i ne 1 %then
%do;
proc append base=count_&i data=count_%eval(&i-1);
run;
%end;
%end;
%mend;
%loop(n=&k_interims);
@LuGa wrote:
Dear SAS Gurus,
please help me debugging my loop.
%let k_interims = 5; %let n_1 = 100; %let n_2 = 100; %let n_3 = 100; %let n_4 = 100; %let n_5 = 100; %let i_nullprop_mean = 0.5; %let i_nullprop_SD = 0.1; %let j_alternative_mean = 0.5; %let j_alternative_SD = 0.1; data _null_; do i=1 to &k_interims by 1; s= ' data count_'||trim(left(put(i,3.)))||' (drop=j); length trt sbi 4; if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do; do j = 1 to round(&n_'||trim(left(put(i,3.)))||', 2) by 1; if mod(j, 2) eq 0 then do; trt = 1; sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); end; else do; trt = 0; sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); end; output; end; end; else if '||trim(left(put(i,3.)))||' ne "1" or '||trim(left(put(i,3.)))||' ne 1 then do; set count_'||trim(left(put(i-1, 3.)))||'; do j = 1 to round(&n_'||trim(left(put(i,3.)))||', 2) by 1; if mod(j, 2) eq 0 then do; trt = 1; sbi = rand("Bernoulli", abs(rand("Normal", &j_alternative_mean, &j_alternative_SD))); end; else do; trt = 0; sbi = rand("Bernoulli", abs(rand("Normal", &i_nullprop_mean, &i_nullprop_SD))); end; output; end; end; run; '; call execute(s); end; run;results in right at the first if statement for the case that i=1:
ERROR: File WORK.COUNT_0.DATA does not exist.
I don't understand why SAS does not accept the case:
if '||trim(left(put(i,3.)))||' eq "1" or '||trim(left(put(i,3.)))||' eq 1 then do;
As you can see I tried to resolve by handling i as a character.
In python I would simply put a:
print(i)in between the loop.
How is it possible to debug such cases?
THX and BR
Lukas
Hi Reeza,
the second one does the job as intended.
Thank you and best regards
Lukas
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 25. 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.