【问题标题】:Macro Do loop not working properly in RSUBMIT宏 Do 循环在 RSUBMIT 中无法正常工作
【发布时间】:2016-05-07 19:00:48
【问题描述】:

所以我有这段代码可以正常运行一年,但我需要将其转换为循环,以便它可以在 1970 年到 2015 年之间运行多年。

这是我在 %let 语句中指定的 1 年代码。

%let year=1970
rsubmit; 
data home.historical_returns_&year;
set home.crspdata;
where (year <= &year - 1) and (year >= &year - 5);
returns_count + 1;
by id year;
if first.id or missing(tot_ret) then returns_count = 1;
run;
endrsubmit;

到目前为止,该代码对我来说非常有用。现在,我正在尝试使用循环,所以我会在 1970 年到 2015 年期间使用它。

我想出了这个。看起来效果不错,但年份停留在 1970 年。

%macro GMV;
rsubmit;
%do year=1970 %to 2015;
data home.historical_returns_&year;
set home.crspdata;
where (year <= &year - 1) and (year >= &year - 5);
returns_count + 1;
by id year;
if first.id or missing(tot_ret) then returns_count = 1;
run;
%end;
endrsubmit;

%mend GMV;

%GMV

在日志中,我看到名称中的 &year 实际上从未从 1970 年到 1971 年到 1972 年等发生变化。所以我最终没有得到我需要的 45 个不同的数据集。

有人遇到过这个问题吗?

谢谢!

【问题讨论】:

  • 远程 SAS 会话中宏变量 YEAR 的值是多少?

标签: sas sas-macro


【解决方案1】:

您将远程处理与本地处理混为一谈,这会导致此类问题。你的宏变量不会被更新(我有点惊讶它没有抛出关于 %do 循环的错误,就个人而言)。

rsubmit;

%macro GMV;
%do year=1970 %to 2015;
data home.historical_returns_&year;
set home.crspdata;
where (year <= &year - 1) and (year >= &year - 5);
returns_count + 1;
by id year;
if first.id or missing(tot_ret) then returns_count = 1;
run;
%end;

%mend GMV;

%GMV
endrsubmit;

将整个宏放入 rsubmit 以获得您正在寻找的结果 - 或将整个 rsubmit 放入宏中(我认为这不是一个好主意,尽管 cmets 中的 Tom 指出它可能更安全某些情况下的选项)。

【讨论】:

  • 作为与问题无关的插件:对于大多数用例,您不必创建这样的数据集。一个具有数据集年份 BY 组的数据集可以在您执行此操作的情况下完成您想要的大部分操作。
  • 将宏定义放在 RSUBMIT 块内可能会导致麻烦。 SAS 有时在尝试将代码发送到另一端时似乎会感到困惑,可能会引入意外的令牌中断。我不确定这个问题是否已经解决。调试很痛苦。最好上传定义代码并在远程端 %INC。
  • 最好不要这样写代码我想......我认为我从来没有遇到过这种风格的问题,虽然我已经有几年没有使用提交。我确实运行过涉及通过 RSUBMIT 发送宏的代码并且没有任何问题。但很高兴知道可能有一些。
  • 被我们烧毁的系统将所有内容都封装到一个自动调用宏中。因此,可能是 rsubmit 块与嵌入在另一个宏执行中的宏定义的组合混淆了 SAS。
  • 就这种方法而言 - 如果您正在执行回归或引导程序或类似方法,请在 Google 上“不要循环”以获取更好方法的建议(这适用于很多分析)。 BY 组处理是 SAS 最好和最强大的功能之一。
【解决方案2】:

如果您想在RSUBMIT 的代码中引用宏变量,那么该宏变量需要存在于远程会话中。

%macro GMV(start,end);
   %local year;
   %do year=&start %to &end;
      %syslput year=&year;
      rsubmit;
       data home.historical_returns_&year;
         set home.crspdata;
         by id year;
         where (year <= &year - 1) and (year >= &year - 5);
         returns_count + 1;
         if first.id or missing(tot_ret) then returns_count = 1;
       run;
     endrsubmit;
   %end;
 %mend GMV;

 %GMV(1970,2015);

【讨论】:

  • 这样的代码可以正常工作,我已经使用过了。但是,不能编译宏并且不能在 RSUBMIT 和 ENDRSUBMIT(在远程服务器上)之间分配宏变量。 &YEAR 可用的唯一原因是 %SYSLPUT。您可以使用 %SYSLPUT 发送已编译的宏,但宏引用通常会带来更多麻烦。
猜你喜欢
  • 2021-12-06
  • 2018-10-22
  • 2019-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多