宏以前被认为是经验老道的SAS程序员使用的高级技术。
宏处理器 标准SAS程序中,提交程序后,SAS就编译并立即执行。但宏语句多了一步,在提交之后,SAS会将宏语句传送到宏处理器上,将其转变为SAS标准代码,通常叫做“变换代码”(meta-programming.)
宏和宏变量 SAS宏代码包括两个基本部分:宏命令和宏变量。宏变量通常加一个“&”作为前缀,而宏命令通常加一个“%”作为前缀。
局部VS全局 宏变量有局部宏变量和全局宏变量。如果在宏的内部定义则为局部宏变量,只能在内部使用。如果在开放代码中定义则为全局宏变量。避免两种错误:在宏之外(开放代码)使用局部变量;创建同名的局部变量和全局变量。
启动宏处理器 使用宏指令之前必须将宏系统选项打开,尽管有时默认是打开的。可以用下面代码查看是否打开:
PROC OPTIONS OPTION=MACRO;
RUN;
查看日志,如果看到MACRO
,则打开了;如果看到NOMACRO
,则没有打开。
%let
创建一个宏变量 最简单给宏变量分配一个值的方法是%let
,基本形式为:%LET macro-variable-name=value;
%LET iterations=10;
%LET country=New Zealand;
当赋值字符串时,不需要加引号。除非在开头和结尾有空格,否则从等号到分号的全部内容都是变量值。
&
,注意宏处理器找不到单引号内的宏变量,只能用双引号。如下的例子:DO i=1 to &iterations;
TITLE ”Addresses in &country”;
经宏处理器编译后,语句变成:
DO i=1 to 10;
TITLE ”Addresses in New Zealand”;
一份关于花店销售的数据,变量为顾客ID,销售日期,花的种类,数量 想要一份反映某一种类型花的销售情况数据,宏变量就可以不用编辑数据步和过程步来选择一种花种:
TropicalSales.dat 下载
%LET flowertype = Heliconia;
* Read the data and subset with a macro variable;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
IF Variety = "&flowertype";
RUN;
* Print the report using a macro variable;
PROC PRINT DATA = flowersales;
FORMAT SaleDate WORDDATE18.;
TITLE "Sales of &flowertype";
RUN;
%MACRO macro-name;
macro-text
%MEND macro-name;
%MACRO
语句告诉SAS
这是宏开始,而%MEND
则意味着结束。macro-name
是自己命名的,但mend
后面的macro-name
则是可选的,但加入会使得句子好很多(easier to debug and maintain)。
%
来启动宏:%macro-name
,注意这里可以不用分号。使用前面花店销售的数据:
下面的代码创建了一个名为%SAMPLE
的宏,来将数据按照Quantity
排序,打印出最大销售额的五个观测值(先降序排列,然后用OBS指定最后一行)。然后用标准数据步读取数据,并启动宏:
/* Program */
* Macro to print 5 largest sales;
%MACRO sample;
PROC SORT DATA = flowersales;
BY DESCENDING Quantity;
RUN;
PROC PRINT DATA = flowersales (OBS = 5);
FORMAT SaleDate WORDDATE18.;
TITLE 'Five Largest Sales';
RUN;
%MEND sample;
* Read the flower sales data;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
*proc print;
RUN;
* Invoke the macro;
%sample
MAUTOSOURCE
和SASAUTOS=
系统选项告诉SAS在哪里查找宏。之后,即使宏没有出现在程序中,也可以启动它。%MACRO macro-name(parameter-1=,parameter-2=,...parameter-n=);
macro-text
%MEND macro-name;
%QUARTERLYREPORT
的宏可能这样开始:%MACRO quarterlyreport(quarter=,salesrep=);
&QUARTER
和&SALESREP
。启用这个宏可以用这样的语句:%quarterlyreport(quarter=3,salesrep=Smith)
/* Program */
* Macro with parameters;
%MACRO select(customer=,sortvar=);
PROC SORT DATA = flowersales OUT = salesout;
BY &sortvar;
WHERE CustomerID = "&customer";
RUN;
PROC PRINT DATA = salesout;
FORMAT SaleDate WORDDATE18.;
TITLE1 "Orders for Customer Number &customer";
TITLE2 "Sorted by &sortvar";
RUN;
%MEND select;
* Read all the flower sales data;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
RUN;
*Invoke the macro;
%select(customer = 356W, sortvar = Quantity)
%select(customer = 240W, sortvar = Variety)
%IF condition %THEN action;
%ELSE %IF condition %THEN action;
%ELSE action;
%IF condition %THEN %DO;
SAS statements
%END;
%IF &SYSDAY=Tuesday %THEN %LET country=Belgium;
%ELSE %LET country=France;
%MACRO dailyreports;
%IF &SYSDAY = Monday %THEN %DO;
PROC PRINT DATA = flowersales;
FORMAT SaleDate WORDDATE18.;
TITLE 'Monday Report: Current Flower Sales';
RUN;
%END;
%ELSE %IF &SYSDAY = Saturday %THEN %DO;
PROC MEANS DATA = flowersales MEAN MIN MAX;
CLASS Variety;
VAR Quantity;
TITLE 'Wednesday Report: Summary of Flower Sales';
RUN;
%END;
%MEND dailyreports;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
proc print;
RUN;
%dailyreports