使用调用执行时宏变量问题

发布于 2024-10-01 08:32:38 字数 6310 浏览 5 评论 0原文

我下面有 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

本质上问题就在这里,调用执行中的上述 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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

↘人皮目录ツ 2024-10-08 08:32:38

您可以使用 %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
   */

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
   */
删除→记忆 2024-10-08 08:32:38

您可能需要将数据步骤中的双引号更改为单引号,如下所示:

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

现在宏处理器正在尝试解析第三行中的百分比符号。您可以通过使用单引号隐藏它们来阻止它这样做。

You probably need to change the double quotes to single quotes in your datastep like so:

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

Right now the macro processor is trying to resolve the percentage symbols in the 3rd line. You can stop it from doing this by hiding them using single quotes.

若有似无的小暗淡 2024-10-08 08:32:38

除非您已经从您发布的示例中的宏中削减了很多,否则很难理解为什么您会使用两个宏而不是一个宏来执行此操作(或者实际上为什么您会使用宏来执行此操作) )像这样:

%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 语句,并在 callexecute 数据步骤中使用 put 语句,以便查看在各个点生成的内容?

建议在开发宏应用程序时首先在不使用宏的情况下运行代码,然后添加宏变量并显式 %let 设置它们的值,然后在宏上下文中测试它。之后将转移到调用执行

也许尝试以上几点,然后返回一些我们可以调试的日志输出。您发布的代码中还有一些其他错误/问题,但我没有指出它们,而是假设您正在将其削减以用于 SO 帖子。

顺便说一句,我喜欢使用 data _null_callexecute 来驱动数据驱动代码的想法,我经常使用这种方法。

Unless you've pared back a lot from the macros for the example you've posted, it's difficult to see why you would do this with two macros, rather than just one (or indeed why you'd use macros to do this at all) like this:

%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;

Anyway, wrt your question about what's going on with the macro variables between calls etc., have you tried

  • Running the macros sequentially outside of the call execute method?
  • Setting options mprint mlogic symbolgen; before execution to see debugging info in the log?
  • Using some %put statements in your macros, and put statements in your call execute datastep, in order to see what's being generated at various points?

It's recommended when developing macro applications to first get the code running without using macro at all, then adding macro variables and explicitly %let-ting their values, then testing it in the context of a macro. Moving to call execute would be after that.

Perhaps try a few of the above points and come back with some log output we can debug. There are a couple of other errors/issues in the code you've posted but rather than pointing them out I'm assuming you're paring it back for the SO post.

BTW I like the idea of driving data-driven code using data _null_ with call execute, I use this approach a lot.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文