Suppose you want a list of car manufacturers from the CARS dataset. Easy! Call the %CHARLIST macro from a %PUT statement, like this: The CHARLIST macro generates a list of unique values of a selected variable from a selected dataset. So does PROC FREQ. But, if you don't need statistics, the CHARLIST [...]
The stored compiled macro facility enables you to compile and save your macro definition in a permanent catalog in a library that you specify. The macro is compiled only once. When you call the macro in the current and subsequent SAS® sessions, SAS executes the compiled code from the macro catalog that you created when you compiled the macro.
The stored compiled facility has two main purposes. The first is that it enables your code to run faster because the macro code does not need to be compiled each time it is executed. The second purpose is to help you protect your code. Sometimes you need to share code that you’ve written with other users, but you do not want them to be able to see the code that is being executed. The stored compiled macro facility enables you to share the program without revealing the code. Compiling the macro with the SECURE option prevents the output of the SYMBOLGEN, MPRINT, and MLOGIC macro debugging options from being written to the log when the macro executes. This means that no code is written to the log when the code executes. After the macro has been compiled, there is no way to decompile it to retrieve the source code that created the catalog entry. This behavior prevents the user from being able to retrieve the code. However, it also prevents you from being able to recover the code.
It is very important to remember that there is no way to get back the code from a stored compiled macro. Because of this behavior, you should ALWAYS save your code when creating a stored compiled macro catalog. In order to update a stored compiled macro, you must recompile the macro. The only way to do this is to submit the macro definition again. Another important fact is that a stored compiled macro catalog can be used only on the same operating system and release of SAS that it was created on. So, in order to use a stored compiled macro on another operating system or release of SAS, that macro must be compiled in the new environment. Again, the only way to compile the macro is to resubmit the macro definition.
Save the Macro Source Code
To make it easier for you to save your code, the %MACRO statement contains the SOURCE option. When you create a stored compiled macro, the SOURCE option stores the macro definition as part of a catalog entry in the SASMACR catalog in the permanent SAS library listed on the SASMSTORE= system option.
Here is the syntax needed to create a stored compiled macro with the SOURCE option set:
libname mymacs 'c:\my macro library'; ❶ options mstored sasmstore=mymacs; ❷ %macro test / store source; ❸ libname mylib1 'path-to-my-first-library'; libname mylib2 'path-to-my-second-library'; %mend;
❶ The LIBNAME statement points to the SAS library that will contain my stored compiled macro catalog.
❷ The MSTORED system option enables the stored compiled facility. The SASMSTORE= option points to the libref that points to the macro library.
❸ The STORE option instructs the macro processor to store the compiled version of TEST in the SASMACR catalog in the library listed in the SASMSTORE= system option. The SOURCE option stores the TEST macro definition in the same SASMACR catalog.
Note that the contents of the SASMACR catalog do not contain an entry for the macro source. The source has been combined with the macro entry that contains the compiled macro. To verify that the source has been saved, add the DES= option to the %MACRO statement. The DES= option enables you specify a description for the macro entry in the SASMACR catalog. So for example, you could add the following description when compiling the macro to indicate that the source code has been saved:
%macro test / store source des=’Source code saved with entry’;
You can look at the contents of the macro catalog using the CATALOG procedure:
proc catalog cat=a.sasmacr; contents; run; quit;
You see the description indicating that the source code was saved with the macro entry in the output from PROC CATALOG:
Retrieve the Macro Source Code
When you need to update the macro or re-create the catalog on another machine, you can retrieve the macro source code using the %COPY statement. The %COPY statement enables you to retrieve the macro source code and write the code to a file. Here is the syntax:
%copy test / source outfile='c:\my macro library\test.sas';
This %COPY statement writes the source code for the TEST macro to the TEST.SAS file. Using TEST.SAS, you are now able to update the macro or compile the macro on another machine.
Remember, you should always save your source code when creating a stored compiled macro. Without the source code, you will not be able to update the macro or move the macro to a new environment.
Here are the relevant links for this article:
Always save your code when creating a stored compiled macro was published on SAS Users.
SAS® offers several ways that you can find the top n% and bottom n% of data values based on a numeric variable. The RANK procedure with the GROUPS= option is one method. Another method is The UNIVARIATE procedure with the PCTLPTS= option. Because there are several ways to perform this task, you can choose the procedure that you are most familiar with. In this blog post, I use the SUMMARY procedure to generate the percentile values and macro logic to dynamically choose the desired percentile statistics. After the percentiles are generated, I subset the data set based on those values. This blog post provides two detailed examples: one calculates percentiles for a single variable and one calculates percentiles within a grouping variable.
Calculate Percentiles of a Single Variable
Calculating percentiles of a single variable includes the following steps. Within the macro, a PROC SUMMARY step calculates the percentiles. The subsequent DATA step uses CALL SYMPUTX to create macro variables for the percentile values, and the final DATA step uses those macro variables to subset the data. Here is the code, which is explained in detail below:
/* Create sample data */ data test; do i=1 to 10000; x=ranuni(i)*12345; output; end; drop i; run; proc sort data=test; by x; run; %macro generate_percentiles(ptile1,ptile2); /* Output desired percentile values */ proc summary data=test; var x; output out=test1 &ptile1= &ptile2= / autoname; run; /* Create macro variables for the percentile values */ data _null_; set test1; call symputx("&ptile1", x_&ptile1); call symputx("&ptile2", x_&ptile2); run; %put &&&ptile1; %put &&&ptile2; data test2; set test; /* Use a WHERE statement to subset the data */ where x le &&&ptile1 or x ge &&&ptile2; run; proc print; run; %mend; options mprint mlogic symbolgen; %generate_percentiles(p1,p99) %generate_percentiles(p25,p75)
After creating and sorting the sample data, I begin my macro definition with two parameters that enable me to substitute the desired percentiles in my macro invocation:
The PROC SUMMARY step writes the desired percentiles for variable X to the Test1 data set. The AUTONAME option names the percentile statistics in the following format, <varname>_<percentile> (for example, x_p25).
proc summary data=test; var x; output out=test1 &ptile1= &ptile2= / autoname; run;
Next, I want to store the values of the percentile statistics in macro variables so that I can use them in later processing. I use CALL SYMPUTX to do this, which gives the macro variables the same name as the statistic. To see the resulting values in the log, I use
data _null_; set test1; call symputx("&ptile1", x_&ptile1); call symputx("&ptile2", x_&ptile2); run; %put &&&ptile1; %put &&&ptile2;
The SAS log shows the following:
MLOGIC(GENERATE_PERCENTILES): %PUT &&&ptile1 SYMBOLGEN: && resolves to &. SYMBOLGEN: Macro variable PTILE1 resolves to p1 SYMBOLGEN: Macro variable P1 resolves to 123.22158288 123.22158288 MLOGIC(GENERATE_PERCENTILES): %PUT &&&ptile2 SYMBOLGEN: && resolves to &. SYMBOLGEN: Macro variable PTILE2 resolves to p99 SYMBOLGEN: Macro variable P99 resolves to 12232.136483 12232.136483
I use these macro variables in a WHERE statement within a DATA step to subset the data set based on the percentile values:
data test2; set test; /* Use a WHERE statement to subset the data */ where x le &&&ptile1 or x ge &&&ptile2; run;
Finally, the macro invocations below pass in the desired percentile statistics:
/* Create sample data */ data test; do group='a','b'; do i=1 to 10000; x=ranuni(i)*12345; output; end; end; drop i; run; proc sort data=test; by group x; run; %macro generate_percentiles(ptile1,ptile2); /* Output desired percentile values by group */ proc summary data=test; by group; var x; output out=test1 &ptile1= &ptile2= / autoname; run; /* Create macro variables for each value of the BY variable */ /* Create macro variables for the percentile values for each BY group */ /* Create a macro variable that is the count of the unique values of the BY variable */ data _null_; retain count 0; set test1; by group; if first.group then do; count+1; call symputx('val'||left(count),group); call symputx("&ptile1"||'_'||left(count), x_&ptile1); call symputx("&ptile2"||'_'||left(count), x_&ptile2); end; call symput('last',left(count)); run; %put _user_; /* Loops through each value of the BY variable */ %do i=1 %to &last; data test&i; set test; where group="&&val&i"; /* Use an IF statement to subset the data */ if x le &&&ptile1._&i or x ge &&&ptile2._&i; run; proc print; run; %end; %mend; options mprint mlogic symbolgen; %generate_percentiles(p1,p99)
Calculating percentiles has many applications, including ranking data, finding outliers, and subsetting data. Using a procedure in Base SAS® that enables you to request percentile statistics along with the power of the macro language, you can dynamically generate desired values that can be used for further processing and analysis.
Selecting the top n% and bottom n% of observations from a data set was published on SAS Users.