如何在更新宏变量的数据步骤中调用宏并立即使用该值? [英] How to call a macro in a data step that updates a macro variable and use that value immediately?

查看:26
本文介绍了如何在更新宏变量的数据步骤中调用宏并立即使用该值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的例子非常简单,可以用更简单的方法解决.但是,我有兴趣让它发挥作用.以下示例基于 sashelp-library 的 cars-dataset.首先,我有一个宏叫做 fun:

The following example is very simple and might be solvable in an easier way. However, I am interested in making it work. The following example is based on the cars-dataset of the sashelp-library. First, I have a macro called 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(来自输入语句).我用:

Now I want to call the macro but only to update obs (from the input statement). I use:

data work.test;
set mycontents;
if name ne "Type" then do;
      call execute('%nrstr(%fun('||name||');');
      new = &obs;
end;
else new = 5;

运行;

简而言之,这应该迭代 mycontents 的行.然后根据名称调用一个(几个)宏,它会更新 obs.然后我可以简单地用 obs 填充新列.但是,对于所有名称,obs 保持相同的值,即最后一个变量的值.

In short, this should iterate the rows of the mycontents. Then call one (of several) macros depending on name, which updates obs. Then I can simply populate the new column new with obs. However, obs stays the same value for all names, which is the value from the last variable.

推荐答案

这里的问题是双重的.

首先,您不能在此上下文中使用 CALL EXECUTE,因为直到 数据步骤完成运行后才会执行:所以任何取决于 &obs 将无法获得更新的值.您必须使用 dosubl.

First, you cannot use CALL EXECUTE in this context because that doesn't execute until after the data step has completed running: so anything depending on &obs will not be able to get an updated value for that. You'll have to use dosubl.

其次,如果要获取更新的值中间数据步骤,则需要使用 symget('obs'),而不是 &obs.&obs 将在编译数据步骤时解析,因此在执行过程中无法更改;但是 symget(obs) 指示数据步在执行过程中查询符号表.

Second, you need to use symget('obs'), not &obs, if you want to get an updated value mid-data step. &obs will resolve when the data step is compiled, so it cannot change during execution; but symget(obs) instructs the data step to query the symbol table during execution.

这是一个使用 dosubl 执行此操作的示例,与您的示例略有不同.请注意 %global 语句以确保 obs 在数据步骤中可供我们使用(还有其他更好的方法可以将其取回 - 即包装这在 fcmp 函数中并使用 run_macro - 但这是最​​接近你的做法).

Here's an example of doing this with dosubl, minimally changed from your example. Note the %global statement to make sure obs is available to us in the data step (there are other ways to do this to get it back that are better - namely, wrapping this in a fcmp function and using run_macro - but this is closest to how you do it).

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;

这篇关于如何在更新宏变量的数据步骤中调用宏并立即使用该值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆