循环以创建由SAS中的列表组成的多个宏变量

时间:2014-04-05 07:37:24

标签: list macros sas

我是SAS宏写作的新手,我一直在努力为以下实例编写代码。

我有一个列表,它是comp_id和date的组合,如下所示 -

DATA compno_date_list; 
  INPUT compno sdate; 
  DATALINES; 
12490 20090120 
87432 20090120
24643 20090120
87432 20090119
12490 20090105
24643 20090105
;

现在,这是一个示例列表。我需要在一个非常大的数据集上运行这个列表上的一个巨大的宏。由于为每一行(即comp_ID - 日期组合)执行此操作将花费大量时间,因此我计划选择唯一日期并创建具有所有日期的宏变量。对于此宏变量中的每个日期,我需要创建一个宏变量,其中包含与该日期相关的comp_ID列表。所以,我计划运行以下生成' n'宏变量在哪里' n'是以下日期总数 -

%MACRO GET_MACRO_VARS();
%let j = 1;
%let sdate3 = %scan(&sdate1., &j.);
%do %while(&j.<= &ndate.);

proc sql;
  select distinct compno into : n&j.
  separated by ' '
 from compno_date_list where sdate=&sdate3.;
%let j= &j. + 1;
%let sdate3 = %scan(&sdate1., &j.);
%put &j.; 
%put &sdate3.;
%put &(n&j);

%end;
%mend;

%GET_MACRO_VARS();

此处,sdate1是包含所有唯一日期的宏变量,ndate是一个宏变量,其中包含唯一日期总数。

但是如果我运行这段代码,我会在上面宏中的最后3%put语句的日志文件中获得以下值:

1 + 1
20090105
&(n1+ 1)

即。 j被视为字符变量(?)。这是怎么回事?我该如何纠正这个? 谢谢!

1 个答案:

答案 0 :(得分:2)

SAS递归地解决以&#34;%&#34;或者&#34;&amp;&#34;。对于%let语句,它将等号右边的所有内容作为字符串存储到宏变量中(宏变量总是字符串)。

对于&#34;%让j =&amp; j。 + 1;&#34;它执行以下操作:

  1. 解决&#34;&amp; j&#34;所以你要留下&#34;%让j = 1 + 1;&#34;;
  2. 由于SAS没有看到以%或者&amp; a开头的任何内容。在等号的右边,它将j设置为&#34; 1 + 1&#34;。
  3. 为了增加j,您需要将行更改为&#34;%let j =%eval(&amp; j + 1);&#34;。所以步骤如下:

    1. 解决最里面的&#34;%&#34;或&#34;&amp;&#34;这是&#34;&amp; j&#34;,所以该行变为&#34;%let j =%eval(1 + 1);&#34;。
    2. 解析&#34;%eval(1 + 1)&#34;所以该行变为&#34;%let j = 2;&#34;。
    3. 将j设置为&#34; 2&#34;。
    4. 另外,获取名称由另一个变量定义的变量值的语法是&amp;&amp; n&amp; j so&amp;(n&amp; j)将不起作用。

      话虽如此,一个更简单的方法来做你想做的事情如下:

      %do j=1 %to %sysfunc(countw(&sdate1));
        proc sql;
          select distinct compno into : n&j separated by ' '
          from compno_date_list where sdate=%scan(&sdate1, &j);
        quit;
        %put &&n&j;
      %end;
      

      有一点需要注意的是,如果您正在处理大型数据集,您可能希望尝试通过在数据步骤中使用多个输出数据集或尽可能使用哈希对象来避免为每个日期重复数据集,因为这样做这似乎是一项非常耗时的任务。