SAS Macro独立工作,但不是在循环时

时间:2015-07-25 00:59:23

标签: sas

我有一个大型数据集,我在那里存储宏参数。宏本身用于调用许多其他宏,每个宏都运行许多操作。

理想情况下,我想使用另一个宏来遍历数据集的每一行,构造(使用:CALL)宏调用,将其存储在宏变量PUT &CALL.;中,然后调用在循环的每次迭代中使用变量(使用 %macro OUTER_LOOP(DS); %let K = ; %COUNT_ROWS(DS, K); /* This stores the number of rows in DS in K. */ %do i = 1 %to &K.; proc sql noprint; ...; quit; /* Create the macro call, and store it in :CALL. */ %put &CALL.; %end; %mend; %OUTER_LOOP; )即:

CALL EXECUTE();

这不能按预期工作:我的宏中存在的一些内部检查表明缺少由宏创建的几个数据集。奇怪的是,当我在宏循环中运行它时(即我手动创建宏调用,逐行并执行它),不会发生错误。

有没有人遇到过这个问题?如果是这样,是否有人熟悉仍然允许我循环宏调用的解决方案?我知道class I(object): pass class A(I): pass class B(I): pass my_parents = [A, B] class C(*my_parents): pass (在数据步骤中)在不同的时间运行宏的不同部分 - 在这种情况下发生了什么?

3 个答案:

答案 0 :(得分:0)

我会在DO循环中添加%put Loop iterating: i=&i k=&k ;。这将让你看到循环迭代的次数。一种可能性是循环比你想要的更早退出。如果是这种情况,原因可能是您在%Outer_Loop中用于循环的宏变量i与您在其中一个内部宏中使用的另一个宏变量i之间的冲突。作为一般规则,将宏变量定义为它们所定义的宏的%LOCAL是个好主意。这样做可以防止这种宏变量冲突。但是没有看到内在的宏,那只是一种可能性。

您还可以在do循环中添加%put %superq(Call) ;。这将显示正在生成的宏调用,因此您可以检查是否在每次调用中获得了预期的参数值。

答案 1 :(得分:0)

最有可能是一个范围问题。您的子宏可能会覆盖调用宏中宏变量的值。

您可以使用%local语句将所有变量声明为局部变量来解决此问题。如果在宏运行后需要访问宏变量,请将它们显式声明为%global

因此,对于上面列出的宏,您需要以下行:

%local k i;

不要忘记你需要为任何被调用的子宏执行此操作,等等......

答案 2 :(得分:0)

通过自己生成代码,可以避免很多这类问题。对于您的示例,您可以将生成代码的逻辑从SQL移动到数据步骤,然后将宏只需要数据步骤而不是宏。您甚至不需要提前知道数据集中的观察数量。

filename code temp ;
data _null_;
    set DS ;
    file code ;
    put '.... generated code based on values in current data ... ;
run;
%include code / source2 ;