Macro returning a value

后端 未结 3 588
清酒与你
清酒与你 2021-02-13 19:56

I created the following macro. Proc power returns table pw_cout containing column Power. The data _null_ step assigns the val

相关标签:
3条回答
  • 2021-02-13 20:11

    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.

    0 讨论(0)
  • 2021-02-13 20:23

    @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;
    
    0 讨论(0)
  • 2021-02-13 20:30

    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.

    0 讨论(0)
提交回复
热议问题