I am trying to learn the SAS %MACRO procedure but something is not working correctly. I am using the SasHelp.PriceData data set and am trying to write some simply code to calculate the median and coefficient of variation for each price feature (preice1-price17). I am running the below code. When I invoke my %DO_Median macro I expect there to be 17 Median_&I table, however the macro does not seem to be generating any output as currently written. What am i missing or not understanding about the %MACRO syntax?
%MACRO DO_MEDIAN;
%DO I=1 %TO I=17;
PROC MEANS DATA=SasHelp.PriceData NOPRINT;
VAR price&I;
OUTPUT OUT=work.Medians_&I Median=Med_&I CV=CV_&I;
RUN;
%END;
%MEND DO_MEDIAN;
%DO_MEDIAN;
The first thing you have to understand is, that the macro language is nothing more, but a code-generator or text-replacing-system. You start writing macros, when you have code that you want/have to execute multiple times.
And please don't not write all code in upcase, it makes reading unnecessary difficult.
Replace the line
%DO I=1 %TO I=17
with
%DO I=1 %TO 17;
The first thing you have to understand is, that the macro language is nothing more, but a code-generator or text-replacing-system. You start writing macros, when you have code that you want/have to execute multiple times.
And please don't not write all code in upcase, it makes reading unnecessary difficult.
Replace the line
%DO I=1 %TO I=17
with
%DO I=1 %TO 17;
Remember to check your log.
You can add the following code to your macros to help with debugging:
options mprint symbolgen;
options mlogic;
I find the MLOGIC can add to much so I don't always use that, but you should be aware it exists when working with macros.
@tgrandchamp wrote:
I am trying to learn the SAS %MACRO procedure but something is not working correctly. I am using the SasHelp.PriceData data set and am trying to write some simply code to calculate the median and coefficient of variation for each price feature (preice1-price17). I am running the below code. When I invoke my %DO_Median macro I expect there to be 17 Median_&I table, however the macro does not seem to be generating any output as currently written. What am i missing or not understanding about the %MACRO syntax?
%MACRO DO_MEDIAN; %DO I=1 %TO I=17; PROC MEANS DATA=SasHelp.PriceData NOPRINT; VAR price&I; OUTPUT OUT=work.Medians_&I Median=Med_&I CV=CV_&I; RUN; %END; %MEND DO_MEDIAN; %DO_MEDIAN;
I understand this is a learning exercise, but I hope you also realize that there's no need for macros in this situation.
PROC MEANS DATA=SasHelp.PriceData NOPRINT;
VAR price1-price17;
OUTPUT OUT=work.medians median=med_1-med_17 cv=cv_1-cv_17;
RUN;
@tgrandchamp wrote:
I am trying to learn the SAS %MACRO procedure but something is not working correctly. I am using the SasHelp.PriceData data set and am trying to write some simply code to calculate the median and coefficient of variation for each price feature (preice1-price17). I am running the below code. When I invoke my %DO_Median macro I expect there to be 17 Median_&I table, however the macro does not seem to be generating any output as currently written. What am i missing or not understanding about the %MACRO syntax?
%MACRO DO_MEDIAN; %DO I=1 %TO I=17; PROC MEANS DATA=SasHelp.PriceData NOPRINT; VAR price&I; OUTPUT OUT=work.Medians_&I Median=Med_&I CV=CV_&I; RUN; %END; %MEND DO_MEDIAN; %DO_MEDIAN;
An aside on the way you are creating your output variable names. Prefixing related values with the statistic may depending on how you use the resulting data make it harder to reference values. If you want to select all of the similar price1 variables it may be more cumbersome. MAY.
SAS does provide a way to append the statistic as suffix to the variable name. Coupled with that plus the variable list you perhaps could do something like:
Proc means data=sashelp.pricedata noprint; var price: ; output out=work.medians median= cv= /autoname; run;
Calculating all of the values in one pass.
Then if you only want to use the values for Price8 later select using Keep= Price8_: ;
The : attached to part of variable name selects all variables that start with that text. So the VAR statement in proc means above is asking to summarize all variables whose names start with PRICE.
If I thought I really needed the variables to start with the statistic , then I might do something like:
%MACRO DO_MEDIAN; PROC MEANS DATA=SasHelp.PriceData NOPRINT; VAR %DO I=1 %TO 17; price&I. %end; ; /* this semicolon ends the VAR statement*/ OUTPUT OUT=work.Medians Median= %DO I=1 %TO 17; Med_&I. %end; CV= %DO I=1 %TO 17; CV_&I. %end; ; RUN; %MEND DO_MEDIAN; %do_median;
to select the variables and specifically name them but in one pass instead of creating 17 different data sets.
Most likely (I'm on my tablet, so can't test it at the moment) this happens:
I=17
is a boolean condition that evaluates to false (which is a numeric zero in SAS, as in most programming environments). The text "I" can never be equal to the text "17".
So your macro do statement evaluates to
%do i = 1 %to 0;
and the loop never executes.
SAS iterative do statements differ from the "for" in C, where you would write
for (i=1;i<=17;i++) {
putting the continuation condition in as the second element, not a target value.
And to clear up a misconception:
%macro is not a procedure, it is a macro statement that invokes the SAS macro preprocessor, so you are switching to a different syntactic environment that is similar in many aspects to Base SAS, but also vastly different in many others.
What do you think is the upper value for I for this %do loop?
%DO I=1 %TO I=17;
What value do you get in the log if you run this statement?
%put I=17;
I am a little late responding, but I found the following article on %MACRO while studying. I hope this helps!
https://support.sas.com/resources/papers/proceedings/proceedings/sugi24/Handson/p149-24.pdf
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.
Ready to level-up your skills? Choose your own adventure.