Reputation: 760
I know I can use call execute to create and execute multiple data steps. But is there a way to generate code for one singular data step, with many repetitive lines of code?
In R for instance I can create a vector of variables, executing some paste/print statement and get something approximating the output I need. As follows:
strings<-c("Exkl_UtgUtl_Flyg",
"Exkl_UtgUtl_Tag",
"Exkl_UtgUtl_Farja",
"Exkl_UtgUtl_Hyrbil",
"Exkl_UtgUtl_Bo",
"Exkl_UtgUtl_Aktiv",
"Exkl_UtgUtl_Annat")
first_string<-strings[1]
other_strings<-strings[strings!=first_string]
gsub("\t", "",gsub("\n","",gsub(",","",paste0(
paste0("DATA IBIS3_5;
Set IBIS3_5;
if ",first_string,"=3 and hjalpvariabel=1 then do;",
first_string,"=1;",
paste0(gsub("Exkl_","",first_string),"SSEK_Pers")," = ",paste0(gsub("^Exkl_","",first_string),"SSEK_PPmedel"),";
end;
else if ",first_string,"=3 then ",first_string,"=2;"),
paste0("else if ",other_strings,"=3 and hjalpvariabel=1 then do;",
other_strings,"=1;",
paste0(gsub("Exkl_","",other_strings),"SSEK_Pers")," = ",paste0(gsub("^Exkl_","",other_strings),"SSEK_PPmedel"),";
end;
else if ",other_strings,"=3 then ",other_strings,"=2;", collapse=","),"run;"))))
I still have to delete the quotes and the bracketed number manually, but that's at least bearable. The final output looks something like this:
DATA IBIS3_5; Set IBIS3_5;
if Exkl_UtgUtl_Flyg=3 and hjalpvariabel=1 then do; Exkl_UtgUtl_Flyg=1;UtgUtl_FlygSSEK_Pers=UtgUtl_FlygSSEK_PPmedel; end; else if Exkl_UtgUtl_Tag=3 and hjalpvariabel=1 then do;Exkl_UtgUtl_Tag=1;UtgUtl_TagSSEK_Pers=UtgUtl_TagSSEK_PPmedel; end; else if Exkl_UtgUtl_Tag=3 then Exkl_UtgUtl_Tag=2;
else if Exkl_UtgUtl_Farja=3 and hjalpvariabel=1 then do;Exkl_UtgUtl_Farja=1;UtgUtl_FarjaSSEK_Pers=UtgUtl_FarjaSSEK_PPmedel; end; else if Exkl_UtgUtl_Farja=3 then Exkl_UtgUtl_Farja=2;
else if Exkl_UtgUtl_Hyrbil=3 and hjalpvariabel=1 then do;Exkl_UtgUtl_Hyrbil=1;UtgUtl_HyrbilSSEK_Pers=UtgUtl_HyrbilSSEK_PPmedel; end; else if Exkl_UtgUtl_Hyrbil=3 then Exkl_UtgUtl_Hyrbil=2;
else if Exkl_UtgUtl_Bo=3 and hjalpvariabel=1 then do;Exkl_UtgUtl_Bo=1;UtgUtl_BoSSEK_Pers=UtgUtl_BoSSEK_PPmedel; end; else if Exkl_UtgUtl_Bo=3 then Exkl_UtgUtl_Bo=2;
else if Exkl_UtgUtl_Aktiv=3 and hjalpvariabel=1 then do;Exkl_UtgUtl_Aktiv=1;UtgUtl_AktivSSEK_Pers=UtgUtl_AktivSSEK_PPmedel; end; else if Exkl_UtgUtl_Aktiv=3 then Exkl_UtgUtl_Aktiv=2;
else if Exkl_UtgUtl_Annat=3 and hjalpvariabel=1 then do;Exkl_UtgUtl_Annat=1;UtgUtl_AnnatSSEK_Pers=UtgUtl_AnnatSSEK_PPmedel; end; else if Exkl_UtgUtl_Annat=3 then Exkl_UtgUtl_Annat=2;
run;
Is there a way of generating this code in SAS, without, having to resort to other programs?
Upvotes: 0
Views: 128
Reputation: 584
The below writes the programs to a file then brings the file bqack into SAS for execution. This is how I avoid macros in almost all cases. 13 years of macros and I ended up with 5 ampersands one night. Vowed to fix.:
* USE WHEN NOT DEBUGGING CODE: ;
* filename TEMP '$MYTEMPFILE';
* USE WHEN DEBUGGING CODE: ;
filename TEMP 'c:\temp\Test.sas';
data _null_ ;
file TEMP ;
set DICT end=eof;
if _n_ = 1 then
do ;
put 'data Africa ; '
/ ' attrib '
;
end;
if label = "" then
put @12 name @30 'label="XX_' name +(-1) '"' ;
else
put @12 name @30 'label="XX_' label +(-1)'"' ;
if eof then
do ;
put @12';'
/ ' set sashelp.SHOES;'
/ 'run;'
;
end;
run;
%include TEMP ;
Upvotes: 0
Reputation: 51611
I do not see the pattern in the code you want to generate so I will leave that part to your imagination. So for the purpose of discussion let's assume you want to generate code like:
var1=var1**2;
var2=var2**2;
You can use conditional logic in the data step that is generating the code via CALL EXECUTE() to generate the beginning (and possible the ending) of the data step you want to generate.
One way is to test when you are on the first (or last) observation.
Example:
data _null_;
set variables end=eof;
if _n_=1 then call execute('data want; set have;');
call execute(cats(variable,'=',variable,'**2;'));
if eof then call execute('run;');
run;
You could also use that _n_=1
test to determine whether or not you need to generate the ELSE.
if _n_>1 then call execute(' else ');
Another way is to use a DO loop to read all of the observations.
data _null_;
call execute('data want; set have;');
do while(not eof);
set variables end=eof;
call execute(cats(variable,'=',variable,'**2;'));
end;
call execute('run;');
stop;
run;
Or if instead of using CALL EXECUTE() you write the code to a file you don't need to worry about generating the beginning or ending of the data step. You can just %INCLUDE the generated code into the middle of a data step.
filename code temp;
data _null_;
file code;
set variables end=eof;
put variable '=' variable '**2;' ;
run;
data want;
set have;
%include code / source2;
run;
Upvotes: 2