简体   繁体   English

如何在SAS中使用&&宏变量

[英]How to use the && macro variable in SAS

I'm working with SAS and I have to create some macro variables within a DO loop. 我正在使用SAS,必须在DO循环中创建一些宏变量。 This is a portion of my code: 这是我的代码的一部分:

%if &dsempty888=0 %then %do;
    data _null_;
    set freq_&&var&i;
        if &&var&i=888888888 then do;
            call symput("cont8_&&var&i",percent);
        end;
    run;
%end;
%if &dsempty888=1 %then %do;
    %let cont8_&&var&i=0;
%end;

%if &dsempty999=0 %then %do;
    data _null_;
    set freq_&&var&i;
        if &&var&i=999999999 then do;
            call symput("cont9_&&var&i",percent);
        end;
    run;
%end;
%if &dsempty999=1 %then %do;
    %let cont9_&&var&i=0;
%end;


%if &dsempty444=0 %then %do;
    data _null_;
    set freq_&&var&i;
        if &&var&i=444444444 then do;
            call symput("cont4_&&var&i",percent);
        end;
    run;
%end;
%if &dsempty444=1 %then %do;
    %let cont4_&&var&i=0;
%end;

This code is inside another DO loop that run from i=1 to &end . 该代码位于另一个从i=1 to &end DO循环中。 With this my macro variables cont4_&&var&i cont8_&&var&i cont9_&&var&i are costantly overwrited...and they become unuseful outside of their loop. 有了这个,我的宏变量cont4_&&var&i cont8_&&var&i cont9_&&var&i被高成本地覆盖了……它们在循环之外变得无用。 I tried to name them &&cont4_&&var&i for example. 例如,我尝试将它们命名为&&cont4_&&var&i But clearly SAS doesn't solve the macro. 但是很明显,SAS不能解决宏。 In practice inside of the loop the macro are created, but I don't know how to call them when I need outside. 实际上,在循环内部创建了宏,但是我不知道在需要外部时如何调用它们。

How can I fix? 我该如何解决?

Thanks in advance. 提前致谢。

You've got a lot of issues here, so let's simplify this some. 这里有很多问题,所以让我们简化一下。 Here's a very simplified example. 这是一个非常简化的示例。 This, for example, does something: 例如,这可以执行以下操作:

%let var1 = age;
%let var2 = height;
%let var3 = weight;

proc freq data=sashelp.class noprint;
  tables age/out=freq_age;
  tables height/out=freq_height;
  tables weight/out=freq_weight;
run;


%macro get_freqs(var_count=);
  %do i = 1 %to &var_count.;
      data _null_;
        set freq_&&var&i;
        call symput("cont4_&&var&i",percent);
      run;
  %end;
%mend get_freqs;

%get_Freqs(var_count=3)

But now if we do 但是现在如果我们这样做

%put cont4_&&var&i;

Of course it doesn't work, since &i has no meaning. 当然,这是行不通的,因为&i没有意义。 So instead we replace that with, say, 1: 因此,我们将其替换为:1:

%put cont4_&&var1;

Now we get something. 现在我们得到了一些东西。 But we don't get anything useful, do we, just the variable name. 但是我们没有得到任何有用的信息,只是变量名。 But - at least that's something! 但是-至少是这样!

Now we don't really need the second & there, right? 现在,我们并不真正需要的第二&那里,对不对?

%put cont4_&var1;

But we need a & before this to use the macro variable: 但是我们需要在&之前使用宏变量:

%put &cont4_&var1;

But now we get a warning message, CONT4_ not resolved . 但是现在我们收到警告消息, CONT4_ not resolved Okay, let's add a second & to delay the resolution of the macro variable until &var1 is resolved. 好的,让我们添加第二个&来延迟宏变量的解析,直到&var1被解析为止。

%put &cont4_&var1;

Well, that helped, now it says CONT4_AGE not resolved . 好吧,这CONT4_AGE not resolved ,现在它说CONT4_AGE not resolved Why not? 为什么不? We used call symput to define that, right? 我们用call symput来定义它,对吗?

The problem is scoping . 问题是范围界定 call symput probably scoped it locally, meaning it was defined in the macro but not outside of the macro. call symput可能将其范围限定在本地,这意味着它是在宏中定义的,而不是在宏外部定义的。 For this we use call symputx and give it a global scope. 为此,我们使用call symputx并将其赋予全局范围。

%macro get_freqs(var_count=);
  %do i = 1 %to &var_count.;
      data _null_;
        set freq_&&var&i;
        call symputx("cont4_&&var&i",percent,'g');
      run;
  %end;
%mend get_freqs;

This tells SAS that I want &cont4_age to be defined outside of the macro. 这告诉SAS,我希望在宏之外定义&cont4_age Otherwise it will only be available locally - inside the macro - and will get cleaned up. 否则,它将仅在本地(在宏内部)可用,并将被清理。

Now, this works: 现在,这有效:

%put &&cont4_&var1;

But if you wanted to iterate over &i again, it's a bit more complex. 但是,如果你想遍历&i再次,这是一个有点复杂。 That's because you need to delay those ampersands multiple times, and allow several passes. 那是因为您需要多次延迟这些“&”号,并允许多次通过。

Here's what works: 这是有效的方法:

%macro iterate_i(var_count=);
  %do i = 1 %to &var_count.;
    %put &&&&cont4_&&var&i.;
  %end;
%mend iterate_i;

%iterate_i(var_count=3);

Why do we need four & s? 为什么我们需要四个 & s? Well, we need to get to &&cont4_&var1 , right? 好吧,我们需要到达&&cont4_&var1 ,对吗? That happens in the first pass. 那是在第一遍中发生的。 Here are the three passes: 这是三个通行证:

&&&&cont4_&&var&i -> &&cont4_&var1 -> &cont4_age -> 5.26... &&&&cont4_&&var&i > &&cont4_&var1 -> &cont4_age > 5.26 ...

Each pass, the following happens: 每次通过,都会发生以下情况:

  • && -> & (and save for next pass) && -> & (并保存以供下一次通过)
  • & -> resolve macro variable & ->解析宏变量

So, that's how you'd iterate over those. 因此,这就是您迭代这些方法的方式。 You can of course explicitly specify at any level the macro variable - so all of these work: 您当然可以在任何级别上显式指定宏变量-因此所有这些工作:

%let i=1;
%put &&&&cont4_&&var&i;
%put &&cont4_&var1;
%put &cont4_age;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM