我正在使用SAS,我必须在DO循环中创建一些宏变量。这是我代码的一部分:
%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;
此代码位于从i=1 to &end
运行的另一个DO循环中。有了这个,我的宏变量cont4_&&var&i
,cont8_&&var&i
,cont9_&&var&i
是远距离的overwrited...and,它们在循环之外变得无用。例如,我试着给它们取名为&&cont4_&&var&i
。但很明显,SAS并不能解决宏观问题。实际上,在循环内部创建了宏,但我不知道如何在需要时调用它们。
我怎么才能修好?
提前谢谢。
发布于 2016-08-25 15:00:52
这里有很多问题,所以让我们简化一下。下面是一个非常简单的例子。例如,这做了一些事情:
%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)
但现在如果我们这么做
%put cont4_&&var&i;
当然它不起作用,因为&i
没有任何意义。相反,我们用,比如说,1:
%put cont4_&&var1;
现在我们得到了一些东西。但是我们没有得到任何有用的东西,不是吗,只是变量名。但是-至少这是件好事!
现在我们不需要第二个&
了,对吧?
%put cont4_&var1;
但是,在此之前,我们需要一个&
来使用宏变量:
%put &cont4_&var1;
但是现在我们收到了一个警告信息,CONT4_ not resolved
。好的,让我们添加第二个&
来延迟宏变量的分辨率,直到&var1
被解析。
%put &cont4_&var1;
嗯,这很有帮助,现在它说CONT4_AGE not resolved
。为什么不行?我们用call symput
来定义它,对吗?
问题在于界定范围。call symput
可能在本地定义了它的作用域,这意味着它是在宏中定义的,而不是在宏之外定义的。为此,我们使用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;
这告诉SAS我希望在宏之外定义&cont4_age
。否则,它将只在本地可用--在宏中--并且将被清理。
现在,这起作用是:
%put &&cont4_&var1;
但是,如果您想再次迭代&i
,则会更复杂一些。这是因为您需要多次延迟这些符号,并允许多次传递。
以下是起作用的原因:
%macro iterate_i(var_count=);
%do i = 1 %to &var_count.;
%put &&&&cont4_&&var&i.;
%end;
%mend iterate_i;
%iterate_i(var_count=3);
为什么我们需要四个&
?我们得去&&cont4_&var1
,对吧?这在第一关就发生了。以下是三张通行证:
&&&&cont4_&&var&i
-> &&cont4_&var1
-> &cont4_age
-> 5.26.
每过一次,就会发生以下情况:
&&
-> &
(并保存到下一关)&
->解析宏变量所以,这就是你迭代这些的方法。当然,您可以在任何级别显式地指定宏变量--所以所有这些工作:
%let i=1;
%put &&&&cont4_&&var&i;
%put &&cont4_&var1;
%put &cont4_age;
https://stackoverflow.com/questions/39148162
复制相似问题