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;

但是 01 不同。正确的?因此,让我们将它们设为宏变量(而不是一个宏变量)。

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

注意我在这里没有使用 &i.,因为那样会造成混淆。相反,我会使用不同的东西,&mv..

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

但无论哪种方式都是可行的。