Макрос, возвращающий значение

Я создал следующий макрос. 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 ответа

@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;

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

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

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

Другие вопросы по тегам