我可以更改 SAS 中 CALL EXECUTE 堆栈的执行顺序吗?

发布于 2024-08-04 01:58:14 字数 503 浏览 3 评论 0原文

我使用 SAS 9.1.3 在 DATA 步骤中调用宏,但该宏生成 PROC REPORT 步骤,因此我使用 CALL EXECUTE 来调用它,生成所有这些 PROC REPORT 步骤,然后在数据步。

我使用的是一个数组,每次都会对该数组中的每个元素执行该宏:

DATA macro_test;
  ARRAY questions[3] $ 32 ('question1' 'question2' 'question3');

  DO i=1 to 3;
    a_question = questions(i);
    CALL EXECUTE( "%report_by_question(a_question)" ); 
  end;

RUN;

问题是,报告输出(通常)向后输出 - 它将首先打印问题 3,然后打印问题 2,然后

打印问题 1。一种修改 CALL EXECUTE 的执行顺序的方法,以便我可以按顺序打印问题报告,或者它只是做自己的事情?

谢谢!

I'm using SAS 9.1.3 to call a macro in a DATA step, but the macro generates a PROC REPORT step, so I am using CALL EXECUTE to call it, generate all those PROC REPORT steps, and then execute them all after the DATA step.

I'm using an array, and the macro is executed each time for every element in this array:

DATA macro_test;
  ARRAY questions[3] $ 32 ('question1' 'question2' 'question3');

  DO i=1 to 3;
    a_question = questions(i);
    CALL EXECUTE( "%report_by_question(a_question)" ); 
  end;

RUN;

The thing is, the report outputs are coming out (usually) backwards - it will print question3 first, then 2, then 1.

Is there a way to modify the execution order of CALL EXECUTE so I can have the question reports print in order, or does it just do its own thing?

Thanks!

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

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

发布评论

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

评论(3

极度宠爱 2024-08-11 01:58:14

我假设您对 callexecute() 行的意思更像是这样:

 CALL EXECUTE( "%report_by_question(" || trim(left(a_question)) || ");" ); 

使用测试宏,我得到一些像这样的日志行,显示 callexecute()s正在以正确的顺序发生。你得到类似的东西吗?

%macro report_by_question(a);
data test_&a;
  do i=1 to 10000000;
    output;
  end;
run;
%mend;

日志

NOTE: CALL EXECUTE generated line.
1   + data test_question1;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION1 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           6.14 seconds
      cpu time            0.45 seconds


1   +                                                                   ;
2   + data test_question2;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION2 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           3.87 seconds
      cpu time            0.53 seconds


2   +                                                                   ;
3   + data test_question3;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION3 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           3.12 seconds
      cpu time            0.45 seconds

I assume you mean something more like this for yout call execute() line:

 CALL EXECUTE( "%report_by_question(" || trim(left(a_question)) || ");" ); 

With a test macro I get some log lines like this, showing that the call execute()s are happening in the right order. Do you get anything similar?

Macro

%macro report_by_question(a);
data test_&a;
  do i=1 to 10000000;
    output;
  end;
run;
%mend;

Logs

NOTE: CALL EXECUTE generated line.
1   + data test_question1;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION1 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           6.14 seconds
      cpu time            0.45 seconds


1   +                                                                   ;
2   + data test_question2;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION2 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           3.87 seconds
      cpu time            0.53 seconds


2   +                                                                   ;
3   + data test_question3;   do i=1 to 10000000;     output;   end; run;

NOTE: The data set WORK.TEST_QUESTION3 has 10000000 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           3.12 seconds
      cpu time            0.45 seconds
赠我空喜 2024-08-11 01:58:14

数据步骤被编译然后执行。 调用execute(str);将str推入输入队列,以便在数据步骤执行完成后将它们弹出。订单被保留,期间。

但是,如果您将宏调用放在双引号字符串中,如下所示:
调用execute("%report(q)");
然后在编译数据步骤时(甚至在数据步骤开始运行之前)调用宏。

如果您不想在编译时调用宏,则可以用宏引用它或将其放在单引号字符串中。下面是一个例子。希望这有帮助。

/* create a dataset with 1 var and 3 obs */
data qs;
  input q $;
cards;
q1
q2
q3
;
run;

/* reporting macro -- a mockup */
%macro report(q=);
  %put report for q=&q;
%mend  report;

/* call the reporting macro for each q */
data _null_;  
  set qs;     
  macro = catx(q, '%report(q=', ')'); 
  call execute(macro);
run;

/* on log
report for q=q1
report for q=q2
report for q=q3
*/


/* to show what happens when the
   macro is invoked during the compile
   time */
data _null_;
  call execute("%report(q=q1)");
  put "after call execute";
run;
/* on log
1   data _null_;
2     call execute("%report(q=q1)");
report for q=q1
3     put "after call execute";
4   run;
after call execute
*/

A data step is compiled and then executed. The call execute(str); pushes the str into the input queue, so that they are popped after the data step is done execution. The order is preserved, period.

However, if you put your macro invocation in the double quoted string as you do in:
call execute("%report(q)");
then the macro is invoked when the data step is compiled, which is even before the data step starts running.

If you don't want to invoke the macro in the compile time, then either macro quote it or put it in the single quoted string. Below is an example. Hope this helps.

/* create a dataset with 1 var and 3 obs */
data qs;
  input q $;
cards;
q1
q2
q3
;
run;

/* reporting macro -- a mockup */
%macro report(q=);
  %put report for q=&q;
%mend  report;

/* call the reporting macro for each q */
data _null_;  
  set qs;     
  macro = catx(q, '%report(q=', ')'); 
  call execute(macro);
run;

/* on log
report for q=q1
report for q=q2
report for q=q3
*/


/* to show what happens when the
   macro is invoked during the compile
   time */
data _null_;
  call execute("%report(q=q1)");
  put "after call execute";
run;
/* on log
1   data _null_;
2     call execute("%report(q=q1)");
report for q=q1
3     put "after call execute";
4   run;
after call execute
*/
如痴如狂 2024-08-11 01:58:14

我更喜欢使用宏语言来完成与宏相关的所有事情。我想权衡是你的程序中散布着很少的宏。但是,要防止程序生成报告,只需注释掉宏调用 (*%loopit;) 此外,您不必键入“question1”、“question2”、“question3”等等!!!
希望这对您有用!

%macro report_by_question(input);
    %put "Question: " &input;
%mend;

%macro loopit;
    %do i=1 %to 3;
        %report_by_question("question&i.");
    %end;
%mend loopit;
%loopit;

I prefer to do everything macro related using macro language. I guess the trade-off is that you have little macros scattered throughout your program. However, to prevent your program from generating reports, just comment out the macro call (*%loopit;) Also, you don't have to type out "question1", "question2", "question3", etc!!!
Hopefully this is useful to you!

%macro report_by_question(input);
    %put "Question: " &input;
%mend;

%macro loopit;
    %do i=1 %to 3;
        %report_by_question("question&i.");
    %end;
%mend loopit;
%loopit;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文