将数据步骤的全局MACRO变量引用到SAS中的proc过程

时间:2019-03-04 02:25:08

标签: sas global-variables

我想在proc过程中使用列表中的变量。这是我的代码的简化版本。

%MACRO CORRMAKER(file,data);
%DO I=1 %TO 2;
%DO J=1 %TO 2;

data _NULL_;
ARRAY VAR1LIST[2] $ A1-A2 ('CAT11' 'CAT12');
ARRAY VAR2LIST[2] $ B1-B2 ('CAT21' 'CAT22');

%GLOBAL VAR1 VAR2;
%LET VAR1=VAR1LIST[&I];
%LET VAR2=VAR2LIST[&J];
run;

proc corr data=&file out=&data&I&J RANK noprob;
var INNERVAR1 INNERVAR2 INNERVAR3 INNERVAR4;
where COND1=&VAR1 COND2=&VAR2;
run;

%END;
%END;
%MEND;

但是VAR1和VAR2没有proc corr程序。如何使用VAR1和VAR2?

谢谢!

2 个答案:

答案 0 :(得分:0)

宏没有本地数组构造。术语“宏数组”是一个隐喻,表示范围可以访问具有相同基本名称和顺序(或索引)后缀的N个宏变量。您可以直接分配充当数组元素的每个变量,也可以使用一些巧妙的代码从文本列表中分离出变量。

“索引”变量使用构造&&&在循环中解析。例如:

%let A2 = 1234;
%let index = 2;

%let var1 = &&A&index;       %* var1 gets 1234;

SAS主管的部分职责是隐式解析宏表达式,并根据需要在令牌上递归。在每个隐式分辨率迭代中,将&的两倍减半。如:

&&A&index -> &A2 -> 1234

您的代码可以更改为

%MACRO CORRMAKER(file,data);

  %local A1 A2 B1 B2 I J VAR1 VAR2;

  %let A1 = CAT11;
  %let A2 = CAT12;

  %let B1 = CAT21;
  %let B2 = CAT22;

  %DO I=1 %TO 2;
  %DO J=1 %TO 2;

    %LET VAR1=&&A&I;
    %LET VAR2=&&B&J;

    proc corr data=&file out=&data&I&J RANK noprob;
      var INNERVAR1 INNERVAR2 INNERVAR3 INNERVAR4;
      where COND1="&VAR1" and COND2="&VAR2";
    run;
  %END;
  %END;

%MEND;

答案 1 :(得分:0)

我不确定为什么要将VAR1和VAR2设置为全局而不是本地。它们似乎仅在此宏中具有含义。在宏的末尾,它们只会在%do循环内分配有最后一个值。

您似乎也不了解宏处理器的工作方式。在生成的数据步骤运行之前,它将完成将宏触发器转换为文本的工作。如果您对语句进行重新排序以反映出以下事实,则将更清楚为什么VAR1和VAR2无法获得所需的值,以及为什么数据步骤根本没有执行任何操作。

%LET VAR1=VAR1LIST[&I];
%LET VAR2=VAR2LIST[&J];

data _NULL_;
ARRAY VAR1LIST[2] $ A1-A2 ('CAT11' 'CAT12');
ARRAY VAR2LIST[2] $ B1-B2 ('CAT21' 'CAT22');
run;

如果您真的想使用变量名CAT11,CAT21等,则只需从I和J进行构建。

%let var1=cat1&i;
%let var2=cat2&j;

如果确实有变量名列表,则将这些列表放在宏变量中。

%let varlist1=cat11 cat12;
%let varlist2=cat21 cat22;
%let var1=%scan(&varlist1,&i);
%let var2=%scan(&varlsit2,&j);

您的WHERE语句也看起来不对。也许您的意思更像是:

%let values1 = cat11 cat12 ;
%let values2 = cat21 cat22 ;
%do i=1 %to 2 ;
%do j=1 %to 2 ;
  ....
  where cond1="%scan(&values1,&i)" and cond2="%scan(&values2,&j)";
  ....
%end;
%end;