How to call a macro in a data step that updates a macro variable and use that value immediately?

☆樱花仙子☆ 提交于 2019-12-11 02:32:21

问题


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;

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;

run;

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.


回答1:


Here the problem is twofold.

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.

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.

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;


来源:https://stackoverflow.com/questions/42031936/how-to-call-a-macro-in-a-data-step-that-updates-a-macro-variable-and-use-that-va

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!