数据步骤中的宏变量

时间:2018-11-16 20:06:43

标签: sas sas-macro

我需要将某个变量的值保存在宏的数据步骤中,然后在同一数据步骤中使用该宏。我尝试使用SYMPUT,但如果我正确理解了以这种方式创建的宏变量,则无法在同一数据步骤内使用(我猜它是在数据步骤的末尾分配的)?

这是一个简化的示例。我有一个数据字段t1,...,t100的列表,这些数据字段表示在某些时间发生的事情,事件由数字表示,而数据字段t_start的数据为我提供了每个我感兴趣的过程的开始时间观察。我想检查是否拥有所有数据,否则将其删除。我要按照以下步骤进行操作。

DATA WANT;
    SET HAVE;

    CALL SYMPUT('START_TIME', t_start);

    DO I=&START_TIME. TO 100;
        IF t_&I. = . THEN DELETE;
    END;
RUN;

这是行不通的,我认为是出于上述原因。有解决方法吗?

备注:

  1. 我简化了情况,正在查看的实际情况更加复杂(例如,变量不称为t1,...t100,而是结构更复杂的东西)。如果可能的话,我想获得与上述方法尽可能接近的方法,因为不同的解决方案可能不适用于我的情况。当然,如果这不可能,那么任何解决方案都将受到欢迎!
  2. 我尝试查看RESOLVE,但是它似乎并没有满足我的要求(或者至少我对它的理解不够,无法使其满足我的期望)。
  3. 作为最后的选择,我可以尝试使用两个数据步骤来解决该问题,一个步骤定义宏变量,另一个步骤使用它来检查和删除不需要的观察值。如果可能的话,我宁愿避免这种解决方案。

更新:我按照解决方案中的建议使用数组解决了问题。

3 个答案:

答案 0 :(得分:2)

您正在尝试使用dataset变量t_starti的值来确定要测试的变量。那就是数组的目的。

DATA WANT;
  SET HAVE;
  array t t1-t100;
  DO I=t_start TO 100;
    IF t(i) = . THEN DELETE;
  END;
RUN;

不需要宏变量,更不用说可以在时间上向后移动并在数据步骤开始运行后修改其代码的宏变量。

答案 1 :(得分:1)

这可能是使用数组的更好方法。 鉴于您发布的内容,此方法可行。如果与您的需求不符,请发布有关您情况的更多详细信息。

data demo;
array t(10);
do row=1 to 100;
do i=1 to 10;
t(i)=rand('integer', 1, 5);
end;
start = rand('integer', 1, 10);
output;
end;
run;

data test;
set demo;

array t(10);



do i=start to dim(t);
if t(i) < 2 then do;
    delete;
    leave;*exits loop;
end;
end;

run;

答案 2 :(得分:1)

当数据步骤正在运行时,该步骤已被“编译”,并且所有与号(&)宏变量解析都已得到解决。正在运行的已编译步骤无法更改其源代码。

如果您两次提交代码,则第一次将记录WARNING: Apparent symbolic reference not resolved.,第二次将没有警告,并且将使用从先前提交中填充的值。 / p>

假设您的数据记录中有很多变量,还有两个前哨变量,其值是这些变量的名称,这些变量标记某些处理的开始和结束。在使用笨拙的数据构造时,可以使用数组来调解对要处理的变量集的访问。

例如:

data have;
input 
 a  b  c  d  e  f  g  h start $ stop $ ; datalines;
 1  2  3  4  5  6  7  8  d  e
11 12 13 14 15 16 17 18  a  b
 0  1  1  2  3  5  8 11  c  h
 1  1  1  1  1  .  1  1  a  e  wont be deleted because . is at f
 1  2  3  4  .  6  7  8  a  h
run;

data want;
  set have;
  array num a--h;
  do i = 1 to dim(num);
    if vname(num(i)) = start then startindex=i;
    if vname(num(i)) = stop  then stopindex=i;
  end;

  do i = min(startindex,stopindex) to max(startindex,stopindex);
    if missing(num(i)) then delete;
  end;
run;