SAS岩论 | Macro系列(1)——入门篇
The following article is from SAS中文论坛 Author 辛岩
Macro系列导读
SAS Macro作为SAS高手不可或缺的一项技能,是因为它功能足够强大,能极大的提升程序开发效率;使你的时间和精力投入在更有价值的事情上。
Macro系列文章,将会逐一奉上SAS Macro的点点滴滴,带你踏上从认识Macro到熟练使用Macro之路。掌握SAS Macro,将会使你的SAS编程能力更上一层楼。
本篇作为SAS Macro系列的开篇文章,通过一个实际问题来引入Macro。带你走入Macro的世界,初步认识它,了解它主要能完成什么事情。
问题说明
客服中心每天都会接到大量的客户咨询、投诉电话,后台系统会记录相关的数据,例如:客户ID、通话开始时间、通话结束时间、通话类型等指标。现需要统计每半小时的话务接入量,数据如下所示:
完成这个统计,需要以下几个过程:
1.将通话开始时间的时间部分提取出来;
2.判断该时间属于48个区间的哪个区间,可以简单的用数字1~48来标记;
3.利用PROC SQL或者PROC FREQ统计每个区间的频数;
DATA步实现
一般情况下,完成1、2两个步骤,会使用类似下面的DATA步实现(非一般情况的方法,请看文末):
data data1;
set sample;
call_time=timepart(call_start_time);
if call_time<'00:30:00't then time_class=1;
else if call_time<'01:00:00't then time_class=2;
else if call_time<'01:30:00't then time_class=3;
else ifcall_time<'02:00:00't then time_class=4;
......
else if call_time<'23:00:00't then time_class=46;
else if call_time<'23:30:00't then time_class=47;
else time_class=48;
run;
可以看到,要想完成区间的标记,需要使用48个IF-ELSE语句来实现;假设要每隔15分钟来统计,就需要写96个IF-ELSE语句!
写完如此大量重复的IF-ELSE语句,将会使人崩溃,而且将会耗费不少时间。有没有办法减少写重复语句的办法?有,可以使用Excel来协助批量生成这些重复的ELSE-IF语句,然后将语句复制到SAS即可。使用Excel的办法看起来很Low,但是有时候特别见效。
Macro实现
除了Excel来协助,另外一个办法就是利用SAS Macro来帮你生成这么多的ELSE-IF语句。先直接上代码,看看Macro如何完成此功能。
%macro mark_time;
data data1;
set sample;
call_time=timepart(call_start_time);
if call_time<'00:30:00't then time_class=1;
%do i=2 %to 47;
%let h=%sysfunc(int(&i/2));
%let m=%eval(%sysfunc(mod(&i,2))*30);
else if call_time<"&h:&m:00"t then time_class=&i;
%end;
else time_class=48;
run;
%mend mark_time;
是不是很简单?利用Macro的循环,帮你生成46个ELSE-IF语句,将这些重复的工作交给Macro来完成。这个过程就好比利用Excel来批量生成ELSE-IF语句,只不过你不用手动去生成,Macro帮你完成。
启用MPRINT OPTION,调用MARK_TIME Macro,在日志中会显示生成的SAS代码:
option mprint;
%mark_time
上面的Macro程序为了使生成的代码好看易理解,特地生成”hh:mm:ss”t形式的日期常量。如果只是实现功能,还可以更直接一点:
%macro mark_time2;
data data2;
set sample;
call_time=timepart(call_start_time);
if call_time<1800 then time_class=1;
%do i=2 %to 47;
else if call_time< (1800 + (&i-1)*1800) then time_class=&i;
%end;
else time_class=48;
run;
%mend mark_time2;
运行该Macro,生成的SAS代码如下:
透过上面的例子,我们可以基本了解Macro是用来做什么的。它就是你的编程助手,协助你批量生成代码,完成特定的功能。我曾在一本书上看到过形容Macro的一句话,我觉得形容的特别贴切:
“When you write a macro program, you are writing a program that writes a program.”
Macro Language和SAS Language(常用的DATA步和PROC步),可以理解为独立的处理的。Macro language是专门由Macro Facility处理,而且是在SAS Language编译前处理的。正如上面的例子,Macro Language(带%的语句)先由Macro Facility处理,生成46个ELSE-IF语句,然后整个DATA步开始编译、执行,得到最终的结果。
Macro除了可以批量生成代码,还可以完成:DATA步,PROC步相互之间的数据传递、根据条件动态执行DATA步或者PROC步、代码的封装,重复利用等等功能。更多内容,请持续关注“SAS中文论坛”微信公众号——“SAS岩论-Macro系列”。
作者:辛岩,从事了多年的SAS数据分析挖掘工作,担任过项目经理、技术顾问、培训讲师等职务,拥有丰富的项目实战经验。
剑指SAS,尽在今朝。欢迎各位技术达人交流,可以长按下面群二维码入SAS中文论坛微信群@Slash,也可以发邮件:slash.xin@hotmail.com。
SAS岩论系列文章,请点击阅读
最后,附上解决上面时间标记问题的,非一般的、不使用Macro的程序:
data data3;
set sample;
h=hour(timepart(call_start_time));
m=minute(timepart(call_start_time));
time_class=h*2 +int(m/30) + 1;
drop h m;
run;
此种方法,属于取巧的一种。通过分析时间和标记区间的关系,直接一步到位;基于时间,直接推算出所属区间。