宏是一种文本,一般来说其编译是在程序执行之前。
宏变量的创建
- %let语句
%let macro_variables = text;
%let是常见的宏变量建立方式,其编译就在执行前。如下例中,想要宏变量test等于数据集customer中的性别。但是%let语句是在执行前编译的,则宏变量等于文本sex,而不是data步中数据集customer的变量sex。
data customer;
format date date9.;
input @1 date date9. name $ sex $ num;
cards;
01May2018 mary F 90
01May2018 harry M 85
01Jun2018 bob M 70
03Jul2018 lily F 30
03Jul2018 lucy F 80
;
run;
options symbolgen;
Data customer1;
Set customer;
%let test = sex;
Run;
- Symputx
想要在数据步中从数据集中动态的获取数据对宏变量赋值,可用symputx路径。
Call symputx(“macro_variable_name”,text);
上例中使用symputx,则每次都将变量sex的值赋予宏变量test,最后一个顾客性别为F,所以最后宏变量test等于F。
options symbolgen;
Data customer1;
Set customer;
Call symputx(“test”,sex);
Run;
- 在PROC SQL过程中创建宏变量
还可以在PROC SQL过程中创建宏变量。
PROC SQL;
SELECT COL1,COL2,... INTO :mvar1, :mvar2,...
FROM table-expression WHERE ... ORDER...;
QUIT;
注意,%let语句可以去掉变量名称文本前后的空格,into子句不会去掉空格。
proc sql noprint;
select distinct date, count(distinct date) into :var_dates seperated by ' ',:num
from customer;
quit;
注意:理解宏变量就是一个文本
%let X=%substr(“ABCD”,2,1);
则X=?,答案为A,因为“ABCD”为一个字符串,第一位为“,所以第二位为A
%let X=%substr(ABCD,2,1);
则X=?,答案为B
二、宏程序
- 宏程序的生成
%MACRO macro-program-name;
程序
%MEND;
- 宏程序控制语句
宏程序的控制语句形式为%if-%then,%do-%end等。与一般的if-then等控制语句不同,宏变量的控制语句判断对象是宏变量。所以,并不是宏程序中就一定要使用%do-%end等宏程序控制语句的。例如,对上述customer数据集,我们想要将同一个日期的数据放到一个数据集中,则有如下两个程序:
程序一
proc sql noprint;
select distinct date, count(distinct date) into :var_dates seperated by ' ',:num
from customer;
quit;
%macro test1;
data s1 s2 s3;
set customer;
%do i = 1 %to &num.;
%let var_date_&i. = %scan(&var_dates,&i,' ');
%if date = "&&var_date_&i.."d %then output s&i.;
%end;
run;
%mend;
%test1;
因为语句%do i = 1 %to &num.;中的i是宏变量,所以可以在语句%let var_date_&i. = %scan(&var_dates,&i,' ');中通过&符号被编译.
而语句%if date = "&&var_date_&i.."d %then output s&i.;是对宏变量date进行判断的,没有名为date的宏变量,所以%if判断语句没有执行,每个数据集里都有5个观测值。
程序二
proc sql noprint;
select distinct date, count(distinct date) into :var_dates seperated by ' ',:num
from customer;
quit;
%macro test1;
data s1 s2 s3;
set customer;
%do i = 1 %to &num.;
%let var_date_&i. = %scan(&var_dates,&i,' ');
if date = "&&var_date_&i.."d then output s&i.;
%end;
run;
%mend;
%test1;
与程序一不同,语句if date = "&&var_date_&i.."d then output s&i.;对数据集中的date变量进行判断,所以会把同一个日期的数据输出到同一个数据集中。结果如下所示,
注意:理解宏程序为文本
%macro counts(rows);
proc freq data = customer;
Tables %if &rows ne %then &rows * ;
Sex;
Run;
%mend counts;
%counts;
其中,当语句%if &rows ne %then &rows * ;的if为真时,则有&rows * sex; 即,
proc freq data = customer;
Tables &rows * Sex;
Run;
当if为假时,则只有Sex; 即
proc freq data = customer;
Tables Sex;
Run;
所以宏程序为文本,且是先编译后执行的。