当作为SAS程序运行时,此代码执行正常:
%MyMacro(foo_val, bar_val, bat_val);
我创建了一个表使用:
DATA analyses;
input title : $32. weight : $32. response : $32.;
datalines;
foo1 bar1 bat1
foo2 bar2 bat2
;
Run Code Online (Sandbox Code Playgroud)
我想为表的MyMacro每一行执行一次analyses.
以下代码似乎只传递字符串值title,weight并且response(而不是数据值foo1等)传递给我的宏(通过调用%put命令测试):
DATA _NULL_ ;
set analyses;
%MyMacro(title, weight, response);
RUN;
Run Code Online (Sandbox Code Playgroud)
如何analyses在将数据值作为参数传递给宏的同时为表的每个记录调用一次宏?目的是为了进行大量分析而实际执行此操作,因此解决方案必须适当地扩展到analyses表中的更多记录.
Joe*_*Joe 10
这部分取决于您的宏正在做什么.如果我们假设你的宏正在做一些打算在数据步骤之外运行的东西(即,它不只是分配一个数据步骤变量),那么你有几个选择.
已经解释了CALL EXECUTE,对于某些情况来说这是一个很好的选择.然而,它有一些缺点,特别是对于宏时序,在某些情况下需要额外注意保护 - 特别是当你在宏中创建宏变量时.Quentin在他的评论中展示了一种解决这个问题的方法(增加%NRSTR了调用),但我发现我更喜欢只使用CALL EXECUTE,这样做比其他方法更有优势 - 特别是,如果我想使用SAS数据在创建我的宏调用时,或者当我不得不在数据步骤中执行某些操作时,可以避免再次读取文件的开销,这就是步骤技术(例如FIRST或LAST,或者某种形式的循环).如果我只是写一个像你一样的数据步骤 - 数据,设置,调用执行,运行 - 我不会使用它.
PROC SQL SELECT INTO通常是我用于列表处理(这主要是这个).在做一些不太复杂的事情时,我更喜欢SQL的简单性; 例如,您可以轻松地获得每个宏调用的一个版本,DISTINCT而无需显式写入proc sort nodupkey或使用第一个/最后一个处理.它还具有调试的优势,您可以将所有宏调用写入结果窗口(如果您不添加noprint),如果我试图了解为什么我的话,这比我的日志更容易阅读调用没有正确生成(并且不采用任何额外的PUT语句).
proc sql;
select catx(',','%macro(',arg1,arg2,arg3)||')'
into :mvarlist separated by ' '
from dataset;
quit;
&mvarlist.
Run Code Online (Sandbox Code Playgroud)
这非常简单地运行它们,并且没有时间问题(因为你只是写了一堆宏调用).
这种方法的主要缺点是在宏变量中最多有64k个字符,所以如果你写了大量的这些,你就会遇到这个问题.在那种情况下使用CALL EXECUTE或%INCLUDE文件.
%INCLUDE文件SELECT INTO在调用超过字符限制时替换,或者如果发现调用文本文件有用(例如,如果您以批处理模式运行它,则可能是比日志或列表输出更容易获得和/或解析).您只需将调用写入文件,然后再写入%INCLUDE该文件.
filename myfile temp; *or a real file if you want to look at it.;
data _null_;
set dataset;
file myfile;
put @1 catx(',','%macro(',arg1,arg2,arg3)||')';
run;
%include myfile;
Run Code Online (Sandbox Code Playgroud)
我不再使用这么多,但它是一种常用的技术,特别是旧的SAS程序员使用,这很有用.
DOSUBL是一种相对较新的方法,并且在某种程度上可以用来替换,CALL EXECUTE因为它的默认行为通常比你的直觉更接近你的预期CALL EXECUTE.doc页面确实是最好的例子,说明它的工作方式不同; 基本上,它通过让每个单独的调用看起来导入并将宏变量从/向调用环境导出来修复时序问题,这意味着每次迭代DOSUBL都在一个不同的时间运行,而不是CALL EXECUTE在一堆中运行所有内容,宏环境是'fixed'(即,对宏变量的任何引用都是在运行时修复的,除非你把它弄得乱七八糟%NRSTR).
值得一提的另一件事是语言RUN_MACRO的一部分FCMP.这允许您完全运行宏并将其内容导回到数据步骤,这在某些情况下是一个有趣的选项(例如,您可以围绕选择了某些内容的PROC SQL进行调用,然后导入作为变量的数据集,所有在一个datastep).如果你这样做是为了调用一个宏来分配一个数据步骤变量,而不是运行一个不需要导入到数据步骤中的东西的过程,那么它是适用的,但如果你这样做是值得考虑的事情确实希望在调用该进程的数据集中返回所有数据.
你可以使用CALL EXECUTE:
data _null_;
set analyses;
call execute('%nrstr(%MyMacro('||title||','||weight||','||response||'))');
run;
Run Code Online (Sandbox Code Playgroud)