2011-09-13 8 views
11

Ho creato la seguente macro. Proc power restituisce la tabella pw_cout contenente la colonna Power. Il passo data _null_ assegna il valore nella colonna Power di pw_out alla variabile macro tpw. Voglio la macro per restituire il valore di tpw, in modo che nel programma principale, posso chiamarlo al punto dati come:Macro restituendo un valore

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

ecco il codice della 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; 

risposta

2

È non posso fare ciò che stai cercando di fare in questo modo. I macro in SAS sono leggermente diversi rispetto a un tipico linguaggio di programmazione: non sono subroutine che è possibile chiamare, ma piuttosto solo codice che genera altro codice SAS che viene eseguito. Poiché non è possibile eseguire proc power all'interno di un passaggio di dati, non è possibile eseguire questa macro da un passaggio di dati. (Immagina di copiare tutto il codice all'interno della macro nel passaggio dei dati: non funziona.)

Un modo per fare ciò che vuoi è leggere ogni osservazione da tmp uno alla volta, quindi eseguire il proc power. Vorrei fare qualcosa di simile:

/* 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; 

Utilizzando proc append è possibile memorizzare i risultati di ogni giro di uscita.

Non ho controllato questo codice in modo che potrebbe avere un bug, ma questo approccio funzionerà.

10

@itzy è corretto nel sottolineare perché il tuo approccio non funzionerà. Ma il numero è una soluzione che mantiene lo spirito del tuo approccio: devi creare una funzione di calcolo della potenza uisng PROC FCMP. Infatti, AFAIK, per chiamare una procedura all'interno di una funzione in PROC FCMP, è necessario avvolgere la chiamata in una macro, quindi ci si trova quasi lì.

Ecco la macro - leggermente modificato (per lo più per risolvere la dichiarazione 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; 

Ora creiamo una funzione che chiameremo:

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; 

E, infine, si può provare utilizzando questa funzione in un passo di dati:

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

È possibile richiamare una macro che chiama pr ocedure, ecc. (come nell'esempio) all'interno di un datastep usando call execute(), ma può risultare un po 'complicato e difficile da eseguire il debug.