【问题标题】:Loop to create multiple macro variables consisting of lists in SAS循环创建由 SAS 中的列表组成的多个宏变量
【发布时间】:2014-04-05 07:37:24
【问题描述】:

我是 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 被视为字符变量(?)。为什么会发生这种情况,我该如何纠正? 谢谢!

【问题讨论】:

  • 拜托,拜托,不要学习这样写宏。这是一个非常糟糕的编程风格的例子。您几乎不需要编写没有参数的宏;以这种方式可以做的所有事情都可以在没有不必要的宏循环的情况下完成。如果您详细说明为什么要执行上述操作(即,您将如何处理这些宏列表),我很乐意向您展示执行此操作的正确方法。

标签: list macros sas


【解决方案1】:

SAS 递归解析以“%”或“&”开头的所有内容。对于 %let 语句,它将等号右侧的所有内容作为字符串存储到宏变量中(宏变量始终是字符串)。

对于“%let j= &j. + 1;”它执行以下操作:

  1. 解析“&j”,留下“%let j= 1 + 1;”;
  2. 由于 SAS 在等号右侧看不到任何以 % 或 & 开头的内容,因此将 j 设置为“1 + 1”。

为了增加 j,您需要将行更改为“%let j=%eval(&j + 1);”。所以步骤变成了以下:

  1. 解析最里面的“%”或“&”也就是“&j”,所以行变成“%let j=%eval(1 + 1);”。
  2. 解析“%eval(1 + 1)”,使该行变为“%let j=2;”。
  3. 将 j 设置为“2”。

此外,获取名称由另一个变量定义的变量的值的语法是 &&n&j,因此 &(n&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;

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

【讨论】:

    猜你喜欢
    • 2017-11-01
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多