宏返回值

发布于 2024-12-04 14:20:00 字数 774 浏览 0 评论 0原文

我创建了以下宏。 Proc power 返回包含列 Power 的表 pw_coutdata _null_ 步骤将 pw_outPower 列中的值分配给宏变量 tpw。我希望宏返回 tpw 的值,以便在主程序中,我可以在 DATA 步骤中调用它,如下所示:

data test;
   set tmp;
   pw_tmp=ttest_power(meanA=a, stdA=s1, nA=n1, meanB=a2, stdB=s2, nB=n2);
run;

这是宏的代码:

%macro ttest_power(meanA=, stdA=, nA=, meanB=, stdB=, nB=);


proc power; 
   twosamplemeans test=diff_satt 
   groupmeans = &meanA | &meanB 
   groupstddevs = &stdA | &stdB
   groupns = (&nA &nB)
   power = .;    
   ods output Output=pw_out;
run;

data _null_;
    set pw_out;
    call symput('tpw'=&power);
run;

&tpw
%mend ttest_power;

I created the following macro. Proc power returns table pw_cout containing column Power. The data _null_ step assigns the value in column Power of pw_out to macro variable tpw. I want the macro to return the value of tpw, so that in the main program, I can call it in DATA step like:

data test;
   set tmp;
   pw_tmp=ttest_power(meanA=a, stdA=s1, nA=n1, meanB=a2, stdB=s2, nB=n2);
run;

Here is the code of the macro:

%macro ttest_power(meanA=, stdA=, nA=, meanB=, stdB=, nB=);


proc power; 
   twosamplemeans test=diff_satt 
   groupmeans = &meanA | &meanB 
   groupstddevs = &stdA | &stdB
   groupns = (&nA &nB)
   power = .;    
   ods output Output=pw_out;
run;

data _null_;
    set pw_out;
    call symput('tpw'=&power);
run;

&tpw
%mend ttest_power;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冰之心 2024-12-11 14:20:00

@itzy 正确地指出了为什么你的方法行不通。但是有一个解决方案可以保持您的方法的精神:您需要使用 PROC FCMP 创建一个功率计算函数。事实上,据我所知,要从 PROC FCMP 中的函数内调用过程,您需要将调用包装在宏中,这样就差不多了。

这是您的宏 - 稍作修改(主要是修复 symput 语句):

%macro ttest_power;

  proc power; 
     twosamplemeans test=diff_satt 
     groupmeans = &meanA | &meanB 
     groupstddevs = &stdA | &stdB
     groupns = (&nA &nB)
     power = .;    
     ods output Output=pw_out;
  run;

  data _null_;
      set pw_out;
      call symput('tpw', power);
  run;

%mend ttest_power;

现在我们创建一个将调用它的函数:

proc fcmp outlib=work.funcs.test;

  function ttest_power_fun(meanA, stdA, nA, meanB, stdB, nB);
    rc = run_macro('ttest_power', meanA, stdA, nA, meanB, stdB, nB, tpw);
    if rc = 0 then return(tpw);
    else return(.);
   endsub;

run; 

最后,我们可以尝试在数据步骤中使用此函数:

options cmplib=work.funcs;

data test;
   input a s1 n1 a2 s2 n2;
   pw_tmp=ttest_power_fun(a, s1, n1, a2, s2, n2);
 cards;
0 1 10 0 1 10
0 1 10 1 1 10
;
run;

proc print data=test;

@itzy is correct in pointing out why your approach won't work. But there is a solution maintaing the spirit of your approach: you need to create a power-calculation function uisng PROC FCMP. In fact, AFAIK, to call a procedure from within a function in PROC FCMP, you need to wrap the call in a macro, so you are almost there.

Here is your macro - slightly modified (mostly to fix the symput statement):

%macro ttest_power;

  proc power; 
     twosamplemeans test=diff_satt 
     groupmeans = &meanA | &meanB 
     groupstddevs = &stdA | &stdB
     groupns = (&nA &nB)
     power = .;    
     ods output Output=pw_out;
  run;

  data _null_;
      set pw_out;
      call symput('tpw', power);
  run;

%mend ttest_power;

Now we create a function that will call it:

proc fcmp outlib=work.funcs.test;

  function ttest_power_fun(meanA, stdA, nA, meanB, stdB, nB);
    rc = run_macro('ttest_power', meanA, stdA, nA, meanB, stdB, nB, tpw);
    if rc = 0 then return(tpw);
    else return(.);
   endsub;

run; 

And finally, we can try using this function in a data step:

options cmplib=work.funcs;

data test;
   input a s1 n1 a2 s2 n2;
   pw_tmp=ttest_power_fun(a, s1, n1, a2, s2, n2);
 cards;
0 1 10 0 1 10
0 1 10 1 1 10
;
run;

proc print data=test;
南汐寒笙箫 2024-12-11 14:20:00

你无法以这种方式做你想做的事。 SAS 中的宏与典型编程语言中的宏略有不同:它们不是可以调用的子例程,而只是生成要执行的其他 SAS 代码的代码。由于您无法在数据步骤内运行proc power,因此您也无法从数据步骤运行此宏。 (试想一下,将宏内的所有代码复制到数据步骤中 - 这是行不通的。这就是 SAS 中的宏所做的事情。)

实现您想要的操作的一种方法是从 tmp< 读取每个观察结果/code> 一次一个,然后运行 ​​proc power。我会做这样的事情:

/* First count the observations */
data _null_;
  call symputx('nobs',obs);
  stop;
  set tmp nobs=obs;
run;

/* Now read them one at a time in a macro and call proc power */
%macro power;
  %do j=1 %to &nobs;
    data _null_;
       nrec = &j;
       set tmp point=nrec;
       call symputx('meanA',meanA);
       call symputx('stdA',stdA);
       call symputx('nA',nA);
       call symputx('meanB',meanB);
       call symputx('stdB',stdB);
       call symputx('nB',nB);
       stop;
    run;

   proc power; 
     twosamplemeans test=diff_satt 
     groupmeans = &meanA | &meanB 
     groupstddevs = &stdA | &stdB
     groupns = (&nA &nB)
     power = .;    
    ods output Output=pw_out;
  run;

  proc append base=pw_out_all data=pw_out; run;
 %end;
%mend;

%power;

通过使用 proc append ,您可以存储每轮输出的结果。

我还没有检查过这段代码,所以它可能有错误,但这种方法会起作用。

You can't do what you're trying to do this way. Macros in SAS are a little different than in a typical programming language: they aren't subroutines that you can call, but rather just code that generate other SAS code that gets executed. Since you can't run proc power inside of a data step, you can't run this macro from a data step either. (Just imagine copying all the code inside the macro into the data step -- it wouldn't work. That's what a macro in SAS does.)

One way to do what you want would be to read each observation from tmp one at a time, and then run proc power. I would do something like this:

/* First count the observations */
data _null_;
  call symputx('nobs',obs);
  stop;
  set tmp nobs=obs;
run;

/* Now read them one at a time in a macro and call proc power */
%macro power;
  %do j=1 %to &nobs;
    data _null_;
       nrec = &j;
       set tmp point=nrec;
       call symputx('meanA',meanA);
       call symputx('stdA',stdA);
       call symputx('nA',nA);
       call symputx('meanB',meanB);
       call symputx('stdB',stdB);
       call symputx('nB',nB);
       stop;
    run;

   proc power; 
     twosamplemeans test=diff_satt 
     groupmeans = &meanA | &meanB 
     groupstddevs = &stdA | &stdB
     groupns = (&nA &nB)
     power = .;    
    ods output Output=pw_out;
  run;

  proc append base=pw_out_all data=pw_out; run;
 %end;
%mend;

%power;

By using proc append you can store the results of each round of output.

I haven't checked this code so it might have a bug, but this approach will work.

通知家属抬走 2024-12-11 14:20:00

您可以使用调用execute()从数据步骤中调用一个宏来调用过程等(如示例),但它可能会变得有点混乱并且难以调试。

You can invoke a macro which calls procedures, etc. (like the example) from within a datastep using call execute(), but it can get a bit messy and difficult to debug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文