SAS 宏中的循环数组
Looping Arrays in SAS Macro
我对编写宏很陌生,我有一个似乎重复的 sas 数据步骤。是否可以将这段代码放在一个围绕数组循环的sas宏中,这样就不会重复编写?
data vintage;
set data_have;
array amt {4} mob0-mob3;
if dist = 0 then do;
do i = 1 to 4;
amt{i} = dollar_value;
end;
end;
if dist = 1 then do;
do i = 2 to 4;
amt{i} = dollar_val;
end;
end;
if dist = 2 then do;
do i = 3 to 4;
amt{i} = dollar_val;
end;
end;
if dist = 3 then do;
do i = 4 to 4;
amt{i} = dollar_val;
end;
end;
run;
我曾尝试编写以下宏,但不幸的是,它不起作用。
%macro vx (datain, n, var, wo);
data vin;
set &datain;
array amt {4} mob0-mob3;
%let m = %eval(1+i);
%do i=1 %to &n;
%if dist = i %then %do;
%do j=2 %to m;
mob&j = dollar_val;
%end;
%end;
run;
%mend vx;
感谢您的帮助。
首先,这不是你需要宏语言来解决的问题;见汤姆的评论。但无论如何我都会用宏语言回答如何做,因为它是可能的,并且可能有助于你的学习。
将宏语言想象成代码编写者:就像初级程序员一样,您告诉 SAS 您希望 SAS 做什么,他们就会为您做。它们不是 SAS,它们是 编写 SAS,重要的是它们不能自己使用数据集的详细信息:它们只能使用数据集打开之前已知的信息(变量名称 很好,但不是变量中的数据)除非他们编写一些代码来分别找出数据集中的内容。
你正在做的就是写这么多:
if dist = 0 then do;
do i = 1 to 4;
amt{i} = dollar_value;
end;
end;
但是 0
和 1
不同。正确的?因此,让我们将它们设为宏变量(而不是一个宏变量)。
if dist = &mv. then do;
do i = &mv.+1 to 4;
amt{i} = dollar_value;
end;
end;
注意我在这里没有使用 &i.
,因为那样会造成混淆。相反,我会使用不同的东西,&mv.
.
然后,我们需要确保这里的if
和do
是正确的种类。 %do
表示 "write this code many times"。另一方面,do
用于正常的 SAS do 循环,%if
在这两种情况下都相同。
所以在这里,我们要多次写这个代码块,所以%do
整个块;但是在块内部,当我们想说 if dist=...
时,这是常规的 if(它正在查看数据值),而当我们想说 do i = ... to 4
时,它又是常规的 do(它是常规的 SAS do 循环) ,再次取决于数据)。
我们开始吧:
%macro vx (datain, n, var, wo);
data vin;
set &datain;
array mob[&n.]; *do not have to list them, it is by default;
%do mv=1 %to &n;
if dist = &mv then do; *not MACRO if but regular if;
do i = (&mv.+1) to m; *not MACRO loop but regular loop;
mob[i] = dollar_val;
end;
end;
%end;
run;
%mend vx;
再说一次,最好不要使用宏。
data vin;
set &datain.;
array amt[4];
if dist < 4 then do;
do i = (dist+1) to 4;
amt[i] = dollar_value;
end;
end;
run;
但无论哪种方式都是可行的。
我对编写宏很陌生,我有一个似乎重复的 sas 数据步骤。是否可以将这段代码放在一个围绕数组循环的sas宏中,这样就不会重复编写?
data vintage;
set data_have;
array amt {4} mob0-mob3;
if dist = 0 then do;
do i = 1 to 4;
amt{i} = dollar_value;
end;
end;
if dist = 1 then do;
do i = 2 to 4;
amt{i} = dollar_val;
end;
end;
if dist = 2 then do;
do i = 3 to 4;
amt{i} = dollar_val;
end;
end;
if dist = 3 then do;
do i = 4 to 4;
amt{i} = dollar_val;
end;
end;
run;
我曾尝试编写以下宏,但不幸的是,它不起作用。
%macro vx (datain, n, var, wo);
data vin;
set &datain;
array amt {4} mob0-mob3;
%let m = %eval(1+i);
%do i=1 %to &n;
%if dist = i %then %do;
%do j=2 %to m;
mob&j = dollar_val;
%end;
%end;
run;
%mend vx;
感谢您的帮助。
首先,这不是你需要宏语言来解决的问题;见汤姆的评论。但无论如何我都会用宏语言回答如何做,因为它是可能的,并且可能有助于你的学习。
将宏语言想象成代码编写者:就像初级程序员一样,您告诉 SAS 您希望 SAS 做什么,他们就会为您做。它们不是 SAS,它们是 编写 SAS,重要的是它们不能自己使用数据集的详细信息:它们只能使用数据集打开之前已知的信息(变量名称 很好,但不是变量中的数据)除非他们编写一些代码来分别找出数据集中的内容。
你正在做的就是写这么多:
if dist = 0 then do;
do i = 1 to 4;
amt{i} = dollar_value;
end;
end;
但是 0
和 1
不同。正确的?因此,让我们将它们设为宏变量(而不是一个宏变量)。
if dist = &mv. then do;
do i = &mv.+1 to 4;
amt{i} = dollar_value;
end;
end;
注意我在这里没有使用 &i.
,因为那样会造成混淆。相反,我会使用不同的东西,&mv.
.
然后,我们需要确保这里的if
和do
是正确的种类。 %do
表示 "write this code many times"。另一方面,do
用于正常的 SAS do 循环,%if
在这两种情况下都相同。
所以在这里,我们要多次写这个代码块,所以%do
整个块;但是在块内部,当我们想说 if dist=...
时,这是常规的 if(它正在查看数据值),而当我们想说 do i = ... to 4
时,它又是常规的 do(它是常规的 SAS do 循环) ,再次取决于数据)。
我们开始吧:
%macro vx (datain, n, var, wo);
data vin;
set &datain;
array mob[&n.]; *do not have to list them, it is by default;
%do mv=1 %to &n;
if dist = &mv then do; *not MACRO if but regular if;
do i = (&mv.+1) to m; *not MACRO loop but regular loop;
mob[i] = dollar_val;
end;
end;
%end;
run;
%mend vx;
再说一次,最好不要使用宏。
data vin;
set &datain.;
array amt[4];
if dist < 4 then do;
do i = (dist+1) to 4;
amt[i] = dollar_value;
end;
end;
run;
但无论哪种方式都是可行的。