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

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

问题描述

以下示例非常简单,可能会以更简单的方式解决.但是,我有兴趣让它发挥作用.以下示例基于 sashelp-library 的汽车数据集.首先,我有一个名为 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 因为它不会执行,直到 after 数据步骤完成运行:所以任何取决于 &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天全站免登陆