I have 2 macros below that I am trying to execute 1 after another like a loop using a metadata table and the call execute command in a data step.
macro %TWO requires the global variable &names_agg. that is supposed to be created in macro %ONE. However in the below code, &names_agg is blank the first time I run it. If I run it again, it will only keep the value from the last time it is run.
The idea is that every time %ONE is run, a new &names_agg. is created.
What am I doing wrong?
Thanks
%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;
Sorry about the messy log, this is the actual code. The problem is with NAMES_AGG_A _B and _C no resolving correctly
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
Essentially the problem is here, the above put statement in the call execute shows that NAMES_AGG_A resolves to nothing.
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
Call Execute is a facility of the DATA step which allows executing SAS code generated by the DATA step. Also, the data from the DATA step can be used as part of the executable code in the Call Execute. The syntax of the Call Execute routine is rather simple: call execute('argument');
CALL SYMPUT is a SAS® language routine that assigns a value produced in a DATA step to a macro variable. It is one of the DATA step interface tools that provides a dynamic link for communication between the SAS language and the macro facility.
After a macro variable is created, you typically use the variable by referencing it with an ampersand preceding its name (&variable-name), which is called a macro variable reference. These references perform symbolic substitutions when they resolve to their value. You can use these references anywhere in a SAS program.
You can call a macro within a macro. Here is a trivial example. %macro one(dsn); proc print data=&dsn; run; %mend one; %macro two(dslist); %local i; %do i=1 %to %sysfunc(countw(&dslist)); %one(%scan(&dslist,&i)); %end; %mend two; %two(sashelp.
You can delay macro invocations with %nrstr()
, then it works fine.
/* 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
*/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With