SAS Training Vol.6 你是不是也不想写代码?
对于规律的、重复性的 code,懒人都不想多写哪怕一行。要想省体力,就得花脑力。怎么减少重复性 programming?借助宏捷径。
我们今天来接触特定的几个情景。
情景一:label
需要我们写以下这么多可怕的 label statements:

咋办?一行行地复制粘贴替换么?你也不愿意干!
要生成这样一系列的带有共同 prefix 的行标识符标签,我们可以这样偷懒:
%macro label(n);
%do i= 1 %to &n;
label condid&i= "condition ID&i";
%end;
%mend label;
%label(20)
嘿嘿,只要在 data 步里加这个 macro,你就摆脱了最原始的复制粘贴,还是挺爽的吧?
情景二:%goto statement
明白地告诉你:现在我在同一个 folder 底下有四个文件,分别名为 cty_1、cty_2、cty_3 和 cty_4,这四个文件里面的 layout 都一样。但是我就想读里面的三个,不读文件 cty_3,你咋整?是不是也要写成下面这样?

从今晚看了这篇推送开始,咱都有脾气了,要和这些 say goodbye,偷懒一下:
%macro read;
%do i= 1 %to 4;
%if &i= 3 %then
%goto leslie;
data cty_&i;
infile "D:\NESUG\CTY_&I";
input id f96 f97 f98;
run;
%leslie: %end;
%mend read;
这里借助了 %goto statement,这 4 个中第三个我们想做 specific 处理,就可以这样操作,让它跳出数据读取的循环之中。
是不是有懒人那味儿了?
情景三:symput routine、%eval、byte function
把情景二改一下:还是那四个文件,只不过我们想对应地输出三个分别名为 cty_A、cty_B 和 cty_D 的文件,还是任性地不想读第三个文件并输出。
%macro read;
%do i= 1 %to 4;
%if &i= 3 %then
%goto leslie;
data cty_&i;
infile "D:\NESUG\CTY_&I";
input id f96 f97 f98;
call symput("N", byte(%eval(&i + 64)));
run;
data cty_&N;
set cty_&i;
run;
%leslie: %end;
%mend read;
这里 symput routine 是为了动态地生成 macro variable N。另外,之所以加上 64,是因为利用 byte funciton 输出 A 时,A 在 ASCII 编码系统里排第 65 位。
这种批量化地操作是不是省时省力?
情景四:flag variable
我们在处理 raw data 时,经常需要根据一些 variables 的取值来给每个人建立一个 flag variable,来标识每个 subject 某种属性的类别情况,这个时候,macro 就显得非常好用了。

假设我们有这样的 condition,你要不要这样一个条件一个条件地筛,最后建立起一个 error1?
答案很显然,你也头晕。
%macro mdx(ndx, code);
%do i= 1 %to &ndx-1;
dx&i= "&code" or
%end;
dx&ndx= "&code"
%mend mdx;
if %mdx(15, E8710) then error1= 1;
