2011-09-13 13 views
11

Tôi đã tạo macro sau. Proc power trả về bảng pw_cout chứa cột Power. Bước data _null_ chỉ định giá trị trong cột Power của pw_out tới biến vĩ mô tpw. Tôi muốn các macro để trả về giá trị của tpw, do đó trong chương trình chính, tôi có thể gọi nó trong bước DỮ LIỆU như:Macro trả lại giá trị

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

Đây là mã 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; 

Trả lời

2

Bạn không thể làm những gì bạn đang cố gắng làm theo cách này. Các macro trong SAS có một chút khác biệt so với một ngôn ngữ lập trình điển hình: chúng không phải là các chương trình con mà bạn có thể gọi, mà chỉ là mã tạo ra mã SAS khác được thực thi. Vì bạn không thể chạy proc power bên trong một bước dữ liệu, bạn cũng không thể chạy macro này từ bước dữ liệu. (Chỉ cần tưởng tượng sao chép tất cả các mã bên trong macro vào bước dữ liệu - nó sẽ không hoạt động. Đó là những gì một macro trong SAS.)

Một cách để làm những gì bạn muốn là đọc từng quan sát từ tmp tại một thời điểm, và sau đó chạy proc điện. Tôi sẽ làm một cái gì đó như thế này:

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

Bằng cách sử dụng proc append bạn có thể lưu trữ kết quả của mỗi vòng đầu ra.

Tôi chưa kiểm tra mã này để có thể có lỗi, nhưng cách tiếp cận này sẽ hoạt động.

10

@itzy là chính xác trong việc chỉ ra tại sao cách tiếp cận của bạn sẽ không hoạt động. Nhưng có một giải pháp duy trì tinh thần của phương pháp tiếp cận của bạn: bạn cần phải tạo một chức năng tính toán điện bằng PROC FCMP. Trong thực tế, AFAIK, để gọi một thủ tục từ bên trong một hàm trong PROC FCMP, bạn cần phải bọc cuộc gọi trong một macro, vì vậy bạn gần như ở đó.

Đây là macro của bạn - một chút thay đổi (chủ yếu là để sửa chữa các báo cáo 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; 

Bây giờ chúng ta tạo một hàm mà sẽ gọi nó là:

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; 

Và cuối cùng, chúng ta có thể thử sử dụng chức năng này trong bước dữ liệu:

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

Bạn có thể gọi macro gọi pr ocedures, vv (như ví dụ) từ bên trong một datastep sử dụng gọi execute(), nhưng nó có thể hơi lộn xộn và khó gỡ lỗi.