2010-11-11 23 views
5

我有2個宏,我試圖在數據步驟中使用元數據表和調用執行命令循環執行一個接一個。使用調用執行時的宏變量問題

宏%TWO需要全局變量& names_agg。這應該是在宏%ONE中創建的。但是在下面的代碼中,& names_agg在我第一次運行它時是空白的。如果我再次運行它,它將只保留上次運行時的值。

想法是,每次運行%ONE時,都會有一個新的& names_agg。被建造。

我在做什麼錯?

感謝

%macro ONE(condition); 
%global names_agg; 
%let names_agg = ; 

proc sql; 
    select 
     cats(name,"_agg"), 
    into 
     :names_agg separated by " ", 
    from dataset 
    where condition = "&condition." 
    ; 
quit; 
%mend; 

%macro TWO(name_OT); 

data &name_OT.; 
    set &names_agg.; 
run; 

%mend; 

data _null_; 
    length code $32767; 
    set meta_table; 
    code = "%ONE(" || cats(condition) || "); %TWO(" || cats(Name_OT) || ");"; 
    call execute(code); 
run; 

對不起凌亂的日誌,這是實際的代碼。問題是與NAMES_AGG_A _B和_C沒有解決正確

871 data test; 
872 length code $32767; 
873 set c.new_name_OT (obs=1); 
874 code = '%OT_Append(' || cats(portfolio) || ',' || cats(scorecard) || ',' || 
874! cats(event_table) || ',' || 
875   cats(scorecard_type) || ',' || cats(obs_period) || ',' || cats(outcome_period) || 
875! ',' || cats(x_var) || 
876   ',' || cats(y_var) || ',' || cats(use) || ',' || cats(condition) || '); %put 
876! &names_agg_a.; %OT_Append2(' || cats(Name_OT) || ');'; 
877 call execute(code); 
878 run; 

MLOGIC(OT_APPEND): Beginning execution. 
MLOGIC(OT_APPEND): Parameter PORTFOLIO has value MTG 
MLOGIC(OT_APPEND): Parameter SCORECARD has value A 
MLOGIC(OT_APPEND): Parameter EVENT_TABLE has value event_table_name 
MLOGIC(OT_APPEND): Parameter SCORECARD_TYPE has value Application 
MLOGIC(OT_APPEND): Parameter OBS_PERIOD has value 1 
MLOGIC(OT_APPEND): Parameter OUTCOME_PERIOD has value 18 
MLOGIC(OT_APPEND): Parameter X_VAR has value PI 
MLOGIC(OT_APPEND): Parameter Y_VAR has value GB_Odds 
MLOGIC(OT_APPEND): Parameter USE has value Development 
MLOGIC(OT_APPEND): Parameter CONDITION has value 
MLOGIC(OT_APPEND): %LET (variable name is NAMES_AGG_A) 
MLOGIC(OT_APPEND): %LET (variable name is NAMES_AGG_B) 
MLOGIC(OT_APPEND): %LET (variable name is NAMES_AGG_C) 
MPRINT(OT_APPEND): proc sql; 
SYMBOLGEN: Macro variable PORTFOLIO resolves to MTG 
SYMBOLGEN: Macro variable SCORECARD resolves to A 
SYMBOLGEN: Macro variable EVENT_TABLE resolves to event_table_name 
SYMBOLGEN: Macro variable SCORECARD_TYPE resolves to Application 
SYMBOLGEN: Macro variable OBS_PERIOD resolves to 1 
SYMBOLGEN: Macro variable OUTCOME_PERIOD resolves to 18 
SYMBOLGEN: Macro variable X_VAR resolves to PI 
SYMBOLGEN: Macro variable Y_VAR resolves to GB_Odds 
SYMBOLGEN: Macro variable USE resolves to Development 
SYMBOLGEN: Macro variable CONDITION resolves to 
MPRINT(OT_APPEND): select cats("c.",name,"_agg_a"), cats("c.",name,"_agg_b"), 
cats("c.",name,"_agg_c") into :names_agg_a separated by " ", :names_agg_b separated by " ", 
:names_agg_c separated by " " from c.datasets_pit where portfolio = "MTG" and scorecard = "A" 
and event_table = "event_table_name" and scorecard_type = "Application" and obs_period = 1 and 
outcome_period = 18 and x_var = "PI" and y_var = "GB_Odds" and use = "Development" and 
condition = "" ; 
MPRINT(OT_APPEND): quit; 
MLOGIC(OT_APPEND): Ending execution. 
SYMBOLGEN: Macro variable NAMES_AGG_A resolves to 

本質的問題是在這裏,在調用上述PUT語句執行顯示,NAMES_AGG_A解決不了了之。

NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 

MLOGIC(OT_APPEND2): Beginning execution. 
MLOGIC(OT_APPEND2): Parameter NAME_OT2 has value MTG_Dev_OT_1 
SYMBOLGEN: Macro variable NAME_OT2 resolves to MTG_Dev_OT_1 
MPRINT(OT_APPEND2): data c.MTG_Dev_OT_1_ODDS; 
SYMBOLGEN: Macro variable NAMES_AGG_A resolves to 
MPRINT(OT_APPEND2): set ; 
MPRINT(OT_APPEND2): run; 
SYMBOLGEN: Macro variable NAME_OT2 resolves to MTG_Dev_OT_1 
MPRINT(OT_APPEND2): data c.MTG_Dev_OT_1_GINI; 
SYMBOLGEN: Macro variable NAMES_AGG_B resolves to 
MPRINT(OT_APPEND2): set ; 
MPRINT(OT_APPEND2): run; 
SYMBOLGEN: Macro variable NAME_OT2 resolves to MTG_Dev_OT_1 
MPRINT(OT_APPEND2): data c.MTG_Dev_OT_1_DIST; 
SYMBOLGEN: Macro variable NAMES_AGG_C resolves to 
MPRINT(OT_APPEND2): set ; 
MPRINT(OT_APPEND2): run; 
MLOGIC(OT_APPEND2): Ending execution. 
NOTE: There were 1 observations read from the data set C.NEW_NAME_OT. 
NOTE: The data set WORK.TEST has 1 observations and 12 variables. 

NOTE: CALL EXECUTE generated line. 
1 +  proc sql; 
1 +       select    cats("c.",name,"_agg_a"), 
cats("c.",name,"_agg_b"),    cats("c.",name,"_agg_c")   into 
:names_agg_a separated by " ",    :names_agg_b separated by " ", 
2 + :names_agg_c separated by " "   from c.datasets_pit    where portfolio = 
"MTG" and     scorecard = "A" and     event_table = "event_table_name" 
and     scorecard_type = "Application" and 
3 + obs_period = 1 and     outcome_period = 18 and     x_var = "PI" 
and     y_var = "GB_Odds" and     use = "Development" and 
    condition = ""   ;  quit;; data c.MTG_Dev_OT_1_ODDS;  set 
NOTE: PROCEDURE SQL used (Total process time): 
     real time   0.01 seconds 
     cpu time   0.00 seconds 


4 + ; run; 

NOTE: There were 1 observations read from the data set WORK.TEST. 
NOTE: The data set C.MTG_DEV_OT_1_ODDS has 1 observations and 12 variables. 
NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 


4 +   data c.MTG_Dev_OT_1_GINI;  set ; run; 

NOTE: There were 1 observations read from the data set C.MTG_DEV_OT_1_ODDS. 
NOTE: The data set C.MTG_DEV_OT_1_GINI has 1 observations and 12 variables. 
NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 


4 +             data c.MTG_Dev_OT_1_DIST;  set ; run; 

NOTE: There were 1 observations read from the data set C.MTG_DEV_OT_1_GINI. 
NOTE: The data set C.MTG_DEV_OT_1_DIST has 1 observations and 12 variables. 
NOTE: DATA statement used (Total process time): 
     real time   0.00 seconds 
     cpu time   0.00 seconds 

回答

7

你可以用%nrstr()延遲宏調用,然後它可以正常工作。

/* test data */ 
    data dataset; 
    name="a"; condition="1"; output; 
    name="b"; condition=" "; output; 
    name="c"; condition="1"; output; 
    run; 

    data a_agg; v="a_agg"; run; 
    data b_agg; v="b_agg"; run; 
    data c_agg; v="c_agg"; run; 

    data meta_table; 
    condition="1"; name_ot="ot1"; output; 
    condition="2"; name_ot="ot2"; output; 
    condition=" "; name_ot="ot_"; output; 
    run; 

    %macro one(condition); 
    %global names_agg; 
    %let names_agg = ; 
    proc sql noprint; 
     select cats(name,"_agg") into :names_agg separated by " " 
     from dataset where condition = "&condition."; 
    quit; 
    %mend; 

    %*-- just checking --*; 
    %one(condition=1) %put names_agg=&names_agg; 
    %one(condition=2) %put names_agg=&names_agg; 
    %one(condition=) %put names_agg=&names_agg; 
    %*-- on log 
    names_agg=a_agg c_agg 
    names_agg= 
    names_agg=b_agg 
    --*; 

    %macro two(name_ot); 
    %if &names_agg= %then %do; 
     data &name_ot.; run; 
    %end; %else %do; 
     data &name_ot.; 
     set &names_agg.; 
     run; 
    %end; 
    %mend; 

    data _null_; 
     length code $200; 
     set meta_table; 
     code = catt('%one(', condition, ")"); 
     code = catt(code, '%two(', name_ot, ")"); 
     code = catt('%nrstr(', code, ")"); 
     call execute(code); 
    run; 

    /* check */ 
    title ot1; proc print data=ot1; run; title; 
    /* on lst 
    ot1 
    Obs  v 
    1  a_agg 
    2  c_agg 
    */ 
    title ot2; proc print data=ot2; run; title; 
    /* on log 
    NOTE: No variables in data set WORK.OT2. 
    */ 
    title ot_; proc print data=ot_; run; title; 
    /* on lst 
    ot_ 
    Obs  v 
    1  b_agg 
    */ 
+0

謝謝張!我只是添加了%nrstr到我的代碼,它已經解決了我的問題! – MarkG 2010-12-08 23:32:16

0

除非你從宏您發佈的例子回吐回來了不少,這是很難理解爲什麼要這麼做有兩個宏,而不是隻有一個(或者實際上你爲什麼會使用宏來做到這一點的話)是這樣的:

%macro TheOnlyOne(condition,name_OT); 
    proc sql noprint; 
    select cats(name,"_agg") 
    into :names_agg separated by " " 
    from dataset 
    where condition="&condition"; 
    quit; 
    data &name_OT; 
    set &names_agg; 
    run; 
%mend; 

反正WRT你這是怎麼回事與通話之間等宏觀變量的問題,你有沒有試過

  • 運行宏依次外呼叫e xecute方法?
  • 設置options mprint mlogic symbolgen;執行前查看日誌中的調試信息?
  • 在你的宏中使用一些%put語句,在call execute datastep中使用put語句,以便查看各個點上正在生成的內容。

開發時宏觀應用首先得到的代碼,而完全不使用宏運行,然後加入宏變量,並明確%let -ting它們的值,然後在宏觀的背景下,測試它的建議。在此之後轉移到call execute

也許試試以上幾點,並回來一些我們可以調試的日誌輸出。在你發佈的代碼中還有其他一些錯誤/問題,而不是將它們指出來,我假設你正在削減SO帖子。

順便說一句我喜歡使用data _null_call execute來驅動數據驅動代碼的想法,我使用這種方法很多。

+0

sasfrog嗨,我也開始使用一個宏時只運行宏通常它的工作原理,但裏面調用執行和name_agg變量是空的它運行的第一次,但上次運行,如果價值再次運行。 – MarkG 2010-11-11 22:56:30

+0

因爲這個原因,我把它分成2個宏,認爲當宏ONE結束時它會解析&names_agg,所以它可以在宏TWO中使用。再次,這通常正常運行,但呼叫執行存在相同的問題。看起來&name_agg變量只會在調用執行結束時解析,也就是說它可能會根據我在元數據表中指定的內容運行宏x次,但只會在所有宏完成後生成最後一次&name_agg。 – MarkG 2010-11-11 23:09:44

+0

@MarkG,我可以建議的是,你使用我的文章中列出的宏調試技術,也許運行'obs = 1'的'data_null_'步驟,所以它只運行一次。然後我們會有一些日誌來檢查。絕對要做@Rob用單引號的建議。 – sasfrog 2010-11-11 23:54:23

1

您可能需要更改雙引號爲單引號在datastep像這樣:

data _null_; 
    length code $32767; 
    set meta_table; 
    code = '%ONE(' || cats(condition) || '); %TWO(' || cats(Name_OT) || ");"; 
    call execute(code); 
run; 

眼下宏處理器正試圖解決在3號線百分比符號。你可以通過使用單引號隱藏它們來阻止它。

+0

嗨,羅布,我嘗試使用單引號如你所建議的,但問題仍然存在。基本上&names_agg在宏TWO運行之前不會被創建。謝謝你的回答! – MarkG 2010-11-11 22:25:49

+0

+1你@Rob - 我怎麼錯過了? :) – sasfrog 2010-11-11 23:50:48