sas - ejemplos - Macro devolviendo un valor
ejemplos de macros en sas (3)
Creé la siguiente macro. Proc power
devuelve la tabla pw_cout
contiene la columna Power
. El paso data _null_
asigna el valor en la columna Power
de pw_out
a la variable macro tpw
. Quiero que la macro devuelva el valor de tpw
, de modo que en el programa principal, pueda llamarlo en el paso DATA como:
data test;
set tmp;
pw_tmp=ttest_power(meanA=a, stdA=s1, nA=n1, meanB=a2, stdB=s2, nB=n2);
run;
Aquí está el código de la 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;
No puedes hacer lo que intentas hacer de esta manera. Las macros en SAS son un poco diferentes a las de un lenguaje de programación típico: no son subrutinas a las que se puede llamar, sino solo código que genera otro código SAS que se ejecuta. Como no puede ejecutar el proc power
dentro de un paso de datos, tampoco puede ejecutar esta macro desde un paso de datos. (Solo imagine copiar todo el código dentro de la macro en el paso de datos, no funcionaría. Eso es lo que hace una macro en SAS).
Una forma de hacer lo que quiera sería leer cada observación de tmp
uno a la vez, y luego ejecutar el poder de proc. Haría algo como esto:
/* 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;
Al usar proc append
puede almacenar los resultados de cada ronda de salida.
No he comprobado este código por lo que podría tener un error, pero este enfoque funcionará.
@itzy tiene razón al señalar por qué su enfoque no funcionará. Pero hay una solución que mantiene el espíritu de su enfoque: necesita crear una función de cálculo de potencia usando PROC FCMP. De hecho, AFAIK, para llamar a un procedimiento desde dentro de una función en PROC FCMP, debe envolver la llamada en una macro, por lo que casi está allí.
Aquí está su macro - ligeramente modificado (principalmente para corregir la declaración 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;
Ahora creamos una función que lo llamará:
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;
Y finalmente, podemos intentar usar esta función en un paso de datos:
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;
Puede invocar una macro que invoca procedimientos, etc. (como el ejemplo) desde dentro de un paso de datos usando call execute (), pero puede ser un poco desordenado y difícil de depurar.