我是编写宏的新手,我有一个似乎重复的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;
感谢您的帮助。
答案 0 :(得分:1)
首先,这不是你需要宏语言来解决的问题;看汤姆的评论。但是无论如何我会用宏语言来回答这个问题,因为它是可能的,并且可以帮助你学习。
将宏语言看作代码编写者:就像一个初级程序员,你告诉你想要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
说“多次编写此代码”。另一方面,do
用于正常的SAS do循环,在%if
的两种情况下都是相同的。
所以在这里,我们想多次编写这段代码,所以%do
整个块;但是在块内部,当我们想说if dist=...
时是常规的(它正在查看数据值),当我们想说do i = ... to 4
时它又是常规的(它是常规的SAS执行循环) ,再次依赖数据)。
所以我们走了:
%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;
但它无论如何都是可行的。