下面的例子非常简单,可能可以用更简单的方式解决。不过,我有兴趣让它发挥作用。以下示例基于 sashelp-library 的 cars-dataset。首先,我有一个名为 fun 的宏:
proc contents data = sashelp.cars out = mycontents;
run;
%macro fun(var);
proc sql noprint;
select count(distinct(&var.))
into :obs
from sashelp.cars;
quit;
%mend;
现在我想调用宏,但只想更新 obs(从输入语句)。我用:
data work.test;
set mycontents;
if name ne "Type" then do;
call execute('%nrstr(%fun('||name||');');
new = &obs;
end;
else new = 5;
run;
简而言之,这应该迭代 mycontent 的行。然后根据名称调用一个(多个)宏,这会更新 obs。然后我可以简单地用 obs 填充新列 new 。但是,obs 对于所有名称都保持相同的值,即最后一个变量的值。
这里的问题是双重的。
首先,你不能使用CALL EXECUTE
在这种情况下,因为它不会执行,直到after数据步骤已完成运行:所以任何事情都取决于&obs
将无法获得更新的值。你必须使用dosubl https://support.sas.com/resources/papers/proceedings13/032-2013.pdf.
其次,你需要使用symget('obs')
, not &obs
,如果您想获取中间数据步骤的更新值。&obs
将在编译数据步骤时解析,因此在执行期间无法更改;但symget(obs)
指示数据步骤在执行期间查询符号表。
这是执行此操作的示例dosubl
,与您的示例相比变化很小。请注意%global
声明以确保obs
我们可以在数据步骤中使用(还有其他更好的方法可以将其返回 - 即,将其包装在fcmp
功能及使用run_macro
- 但这最接近你的做法)。
proc contents data = sashelp.cars out = mycontents;
run;
%macro fun(var);
%global obs;
proc sql noprint;
select count(distinct(&var.))
into :obs
from sashelp.cars;
quit;
%mend;
data work.test;
set mycontents;
if name ne "Type" then do;
rc = dosubl(cats('%fun(',name,')'));
new = symgetn('obs');
end;
else new = 5;
run;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)