Макрос, возвращающий значение - PullRequest
12 голосов
/ 13 сентября 2011

Я создал следующий макрос. Proc power возвращает таблицу pw_cout, содержащую столбец Power. Шаг data _null_ назначает значение в столбце Power из pw_out макропеременной 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;

Ответы [ 3 ]

11 голосов
/ 19 сентября 2011

@ itzy правильно указал, почему ваш подход не будет работать.Но - это решение, поддерживающее дух вашего подхода: вам нужно создать функцию расчета мощности с использованием PROC FCMP.На самом деле, AFAIK, чтобы вызвать процедуру изнутри функции в 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;
2 голосов
/ 21 сентября 2011

Вы можете вызвать макрос, который вызывает процедуры и т. Д. (Как в примере) из шага данных, используя функцию execute (), но он может стать немного запутанным и трудным для отладки.

2 голосов
/ 13 сентября 2011

Вы не можете делать то, что пытаетесь сделать таким образом.Макросы в SAS немного отличаются от обычных языков программирования: это не подпрограммы, которые вы можете вызывать, а просто код, генерирующий другой исполняемый код SAS.Поскольку вы не можете запустить proc power внутри шага данных, вы также не можете запустить этот макрос из шага данных.(Просто представьте, что вы копируете весь код внутри макроса на шаг данных - это не сработает. Это то, что делает макрос в SAS.)

Один из способов сделать то, что вы хотите, - прочитать каждое наблюдениеот tmp по одному, а затем запустите 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, вы можете сохранять результаты каждого раунда вывода.

Я не проверял этот код, поэтому он может иметьошибка, но этот подход будет работать.

...