SAS宏中的循环数组

时间:2017-06-02 14:15:04

标签: arrays sas 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;

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

首先,这不是你需要宏语言来解决的问题;看汤姆的评论。但是无论如何我会用宏语言来回答这个问题,因为它是可能的,并且可以帮助你学习。

将宏语言看作代码编写者:就像一个初级程序员,你告诉你想要SAS做什么,他们会为你做。他们不是SAS,他们是编写 SAS,而且重要的是他们不能自己使用数据集的细节:他们只能在数据集打开之前使用已知的数据集(变量名称很好,但不是变量中的数据),除非他们编写一些代码来分别找出数据集中的内容。

你正在做的是写这么多:

if dist = 0 then do;
 do i = 1 to 4;
  amt{i} = dollar_value;
 end;
end;

01不一样。对?所以让我们把它们变成宏变量(而不是一个宏变量)。

if dist = &mv. then do;
 do i = &mv.+1 to 4;
  amt{i} = dollar_value;
 end;
end;

注意我这里不使用&i.,因为这会令人困惑。相反,我会使用不同的东西,&mv.

然后,我们需要确保这里的ifdo是正确的类型。 %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;

但它无论如何都是可行的。