我想在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?
谢谢!
我不确定你为什么把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;
宏没有本机数组结构。术语“宏数组”是一个隐喻,用于范围可以访问具有相同基本名称和顺序(或索引)后缀的N个宏变量。您可以直接分配充当数组元素的每个变量,或者您可以使用一些spiffy代码从文本列表中分割出变量。
'indexed'变量使用construct &&&在循环中解析。例如:
%let A2 = 1234;
%let index = 2;
%let var1 = &&A&index; %* var1 gets 1234;
SAS主管职责的一部分是隐式解决宏表达式,根据需要递归令牌。在每次隐式分辨率迭代时,Doubled&s被减半。如:
&&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;