01-29-2017 06:38 AM
%MACRO MERGE; %Do RO=1 %to 5; PROC SORT DATA = MERGED_&RO; BY KEY;%END; RUN; /*what if %END; is placed after RUN*/ %MEND;
I would like to know how SAS process a Macro DO-loop.
Should I place the %END after RUN or before?
If it is placed before RUN, does it mean that the DO-Loop substitute from MERGED_1 to MERGED_5 but it only executes the Proc Sort for MERGED_5?
01-29-2017 07:05 AM
If you look at the log youu will see that RUN is after all sorts.
In this specific case, as 2nd sort is independent of first that realy soesn't matter,
but as a rule better put the %END after RUN, so that each PROC or datastep has its own RUN.
01-29-2017 07:07 AM
A PROC statement always constitutes a step boundary (as does a RUN statement), so all PROC SORT's will be executed.
01-29-2017 09:01 AM
Macro language is not processing your data. It is generating a program. With %END in its current location, the generated program looks like this:
PROC SORT DATA=MERGED_1; BY KEY;
PROC SORT DATA=MERGED_2; BY KEY;
PROC SORT DATA=MERGED_3; BY KEY;
PROC SORT DATA=MERGED_4; BY KEY;
PROC SORT DATA=MERGED_5; BY KEY;
Now it becomes a question of how SAS language would handle this program. The same principles apply with %END moved to after the RUN statement. Then the generated SAS code would look like this:
PROC SORT DATA=MERGED_1; BY KEY; RUN;
PROC SORT DATA=MERGED_2; BY KEY; RUN;
PROC SORT DATA=MERGED_3; BY KEY; RUN;
PROC SORT DATA=MERGED_4; BY KEY; RUN;
PROC SORT DATA=MERGED_5; BY KEY; RUN;
Again, SAS language receives this code, interprets it, and executes it. But macro language is never processing the data, only generating the program.
I agree with everything that Kurt wrote, including the suggestion to move the %END statement so that every PROC SORT will have its own RUN statement.
01-30-2017 04:30 AM
Whilst the guys have answered the techinical part above I would also like to add that making your program readable should be your number 1 priority (unless your dealing with big data). To this end use lower and consistent case, indent blocks etc.:
%macro merge (); %do ro=1 %to 5; proc sort data=merged_&ro.; by key; run; %end; %mend merge;
You will note the dot after the macro variable - not vital, but highlights nicely in the editor, other things like %mend <macro name> rather than just %mend. At the end of the day other people have to look at your code.
Also, a further note, the macro above is pretty much useless. You have create a problem for yourself in code before this by creating separate datasets for the same data as indicated by the merged_1-5. It is rarely a good idea to split up same data, as then each time you code you need to loop over it. A simpler method - if you just had the 5 datasets:
data want; set merged_:; run; proc sort data=want; by key; run;
You could use the indsname option to get filename if necessary.