我有2个宏,我试图在数据步骤中使用元数据表和调用执行命令循环执行1个接一个。
宏%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
本质上问题在于,调用execute中的上述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
答案 0 :(得分: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
*/
答案 1 :(得分:1)
您可能需要在datastep中将双引号更改为单引号,如下所示:
data _null_;
length code $32767;
set meta_table;
code = '%ONE(' || cats(condition) || '); %TWO(' || cats(Name_OT) || ");";
call execute(code);
run;
现在宏处理器正在尝试解析第3行中的百分比符号。你可以通过使用单引号隐藏它们来阻止它这样做。
答案 2 :(得分: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;
无论如何,你的问题是关于调用之间的宏变量发生了什么等等,你试过吗
options mprint mlogic symbolgen;
以查看日志中的调试信息?%put
语句,在put
datastep中使用call execute
语句,以查看在各个点生成的内容?建议在开发宏应用程序时首先运行代码而不使用宏,然后添加宏变量并显式%let
- 它们的值,然后在宏的上下文中测试它。移至call execute
将在此之后。
也许尝试以上几点并返回一些我们可以调试的日志输出。您发布的代码中还有其他一些错误/问题,但不是指出它们,我假设您正在为SO帖子削减它。
BTW我喜欢使用data _null_
call execute
驱动数据驱动代码的想法,我经常使用这种方法。