2011-09-13 31 views
11

Creé la siguiente macro. Proc power devuelve la tabla pw_cout que contiene la columna Power. El paso data _null_ asigna el valor en la columna Power de pw_out a la variable de macro tpw. Quiero que la macro para devolver el valor de tpw, de modo que en el programa principal, se puede llamar así en el paso de datos como:Macro que devuelve un valor

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

Este es 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; 

Respuesta

2

Usted 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 proc power dentro de un paso de datos, tampoco puede ejecutar esta macro desde un paso de datos. (Imagínese 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 desea sería leer cada observación desde tmp uno a la vez, y luego ejecutar el poder de proc. Me gustaría hacer 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; 

Mediante el uso de 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á.

10

@itzy tiene razón al señalar por qué su enfoque no funcionará. Pero existe es 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í es su macro - ligeramente modificado (en su mayoría para fijar 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 vamos a crear una función que lo llamarán:

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, por último, podemos tratar utilizando 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; 
2

Puede invocar una macro que invoca ocedures, 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.

Cuestiones relacionadas