SAS岩论 Macro系列(2)——总述篇

 

SAS Macro作为SAS高手不可或缺的一项技能,是因为它功能足够强大,能极大的提升程序开发效率;使你的时间和精力投入在更有价值的事情上。...

Macro系列导读
SAS Macro作为SAS高手不可或缺的一项技能,是因为它功能足够强大,能极大的提升程序开发效率;使你的时间和精力投入在更有价值的事情上。

Macro系列文章,将会逐一奉上SAS Macro的点点滴滴,带你踏上从认识Macro到熟练使用Macro之路。掌握SAS Macro,将会使你的SAS编程能力更上一层楼。


上期文章“Macro入门篇”通过一个实际的问题引入SAS Macro,对Macro有了一个初步的认识。作为一个编程助手,它能够帮助你生成大量重复性的代码,以此来节省时间,提高编程效率。
Macro系列(2)——总述篇
本期文章同样从一个问题出发,对Macro的功能,及组成部分进行更具体的介绍,继入门后进一步的认识Macro。
问题说明
还是上期文章中客服中心的数据,记录了一天的通话数据。每条通话记录都有通话开始时间、通话结束时间。现需要筛选出大于当天所有通话平均通话时间的数据,以查看其时间分布情况。数据如下所示:
要完成这个功能,需要以下3个步骤:

1.基于通话开始时间和通话结束时间,计算每笔通话的通话时间;

2.计算当天所有通话的平均通话时间;

3.从数据中筛选出大于平均通话的时间;
SAS代码
使用SAS代码来分步解决:

1. 计算通话时间:

data data1;

set sample;

call_duration=call_end_time-call_start_time;

format call_duration time8.;

run;

2. 求平均通话时间;

procsql;

select avg(call_duration) as avg_call_duration

from data1;

quit;

3. 从上一步的结果中查看“平均通话时间”,假设为49.5,然后进行筛选:

data data2;

set data1;

where call_duration>49.5;

run;

这个问题很简单,解决起来也非常容易。甚至可以将一、二步合并,在DATA步中计算通话时间的同时计算平均通话时间。例如:

data data1;

set sample end=last;

call_duration=call_end_time-call_start_time;

format call_duration time8.;

call_all_time+call_duration;

if last then mean_call_durtion=call_all_time/_n_;

run;
问题思考


  1. 如果每天都需要将大于当天平均通话时间的数据筛选出来,是不是意味着需要每天跑完均值计算的代码,然后手动更新到数据筛选的代码中?
  2. 如果你同事也需要完成类似的工作,你将代码发给他,是不是意味着他要将代码中的所有数据集名、变量名都要更改一次?
救星来临
针对第一种情况,如果计算得到的均值能自动传递到筛选过程,是不是就完美了?

针对第二种情况,如果数据集名和变量名只需改一次,是不是就完美了?

Macro Language就是为解决这些问题而生的。它能够实现在DATA步或者PROC步之间传递数据;将代码进行封装,类似函数的功能,通过参数传递动态值,便于重复使用。
Macro总述


Macro Language从构成角度看,主要由两部分:

  • Macro Variables
  • Macro Programs


Macro Variables不同于DATA STEP中的Variables,它与数据集没有任何关系。可以是全局的,在任何地方都可以使用;也可以是某个Macro中的局部变量,只能在该Macro内部使用。

Macro Programs一般情况下,主要有两种用途:

利用Macro的特性批量生成一些SAS代码;

将实现某个功能的代码封装起来,像函数一样,方便共享、重复使用;

因此,针对上面的问题,可以利用Macro Variable和Macro Program的功能,就将这个问题完美解决。

  1. 在求平均值的过程中,将均值存储到一个Macro Variable,在随后的筛选过程中,直接使用这个Macro Variable的值进行筛选即可。
  2. 进一步,将整个过程封装到一个Macro Program中,设置参数为数据集名和变量,在调用时直接传递数据和变量,这样就可以方便的共享、重复使用。
了解内在
学过其他编程语言的小伙伴肯定都听过“宏”,例如C语言中的“#define”语句,通过定义一个宏,例如:“#define age 18;”,在程序编译时,就会将age出现的所有地方,将其全部替换为18。

其实,SAS中的Macro也是一样的道理,尤其是Macro Variable与C语言中的宏可以说是一模一样的,说白了就是替换的功能。虽说是一个很简单的功能,但是有很大的作用。SAS在这个基础之上,将这个功能继续发扬光大,进行了扩展。除了简单直接的替换,还提供更加复杂、灵活的替换。
因此,从本质上讲,无论是Macro Variables还是Macro Program都是文本替换。只不过Macro Programs可以通过Macro中的各种函数、循环、条件控制等其他语句来实现更加复杂、更加灵活的替换。
小贴士

上文中有提到Macro Programs有类似函数的封装功能,但本质上是不一样的:

  • 函数是实现了某个特定功能,调用该函数,完成相应的功能,返回结果;
  • Macro Programs是封装了实现某个功能的SAS代码,在调用该Macro的时候,Macro Facility只是将其替换为相应的SAS代码,仅此而已。


其实Macro Language的构成除了这两个主要部分,还有一些其他的辅助部分:

  • 关于Macro的System Option;
  • DATA步与Macro交互的一些Function、Call Routine;
  • PROC SQL与Macro交互的子句;
因此Macro Language的整个大家庭可以用以下这张图来概括:
通过这两期的文章的介绍说明,相信各位对SAS Macro会有一个相对清晰的认识。它到底是什么,主要由什么组成,能干些什么事情。后面的文章将会依据上图中的结构,来对每个构成部分进行详细的介绍。
要真正掌握一门语言,达到灵活运用的地步,必须要抛开现象看本质,了解其内在的运行机理。下期文章,将会对Macro的运行机制进行深入剖析,更多内容,请持续关注SAS中文论坛——“SAS岩论-Macro系列”。


作者:辛岩,从事了多年的SAS数据分析挖掘工作,担任过项目经理、技术顾问、培训讲师等职务,拥有丰富的项目实战经验。

剑指SAS,尽在今朝。欢迎各位技术达人交流,可以长按下面群二维码入SAS中文论坛微信群@Slash,也可以发邮件:slash.xin@hotmail.com。

更多SAS岩论系列文章
SAS岩论 | Macro系列(1)——入门篇

SAS岩论 | 使用DATA步并行处理超大数据集

SAS岩论|在SAS中如何解决中文乱码问题(1)

SAS岩论|在SAS中如何解决中文乱码问题(2)-干货篇

SAS岩论|SAS EG中如何显示Data步处理进度


    关注 SAS中文论坛


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册