SAS SymputX 和 Symget 函数

SAS SymputX and Symget Function

我尝试通过编写下面的 SAS 代码来构造 Table 2,但我得到的是 Table 1。我不知道我错过了什么。非常感谢帮助。

     &counter = 4

     data new;set set1;
     total = 0;
     a = 1;
     do i = 1 to &counter;
       call symputX('a',a);
       total = total + Tem_&a.;
       a = symget('a')+1;
       call symputX('a',a);
     end;
     run;



      Table 1
      ID    Amt Tem_1   Tem_2   Tem_3   Tem_4   total
       4    500    1        4       5    900    3600
       5    200   50      100     200      0       0
       9    50    40        0       0      0       0
      10    500   70      100     250      0       0



     Table 2
     ID Amt Tem_1   Tem_2   Tem_3   Tem_4   total
      4 500    1        4       5    900     910
      5 200   50      100     200      0     350
      9 50    40        0       0      0      40
     10 500   70      100     250      0     420

不幸的是,您不能那样使用 SYMPUT 和 SYMGET。虽然您可以将它们用于 store/retrieve 宏变量值,但您不能更改执行后发送给编译器的代码。

基本上,SAS 在查看任何数据(这称为编译)之前,必须弄清楚它在数据步循环的每次迭代中应该执行的操作的机器代码。所以问题是,你不能定义 tem_&a. 并期望在执行期间被允许改变 _&a. 是什么,因为它会改变机器代码需要做的事情,而 SAS 无法准备足够了。

因此,您在 &a. 中编写的内容将在程序编译时解析,并且 &a. 在您的数据步骤之前具有的任何值都将成为 tem_&a. 将变成的值。大概是你第一次 运行 这是错误的(&a. does not resolve 然后是关于 & 在变量名中是非法的错误),然后最终 call symput 完成了它的工作并且 &a在循环结束时得到一个 4,并且永远更多你的 tem_&a. 解析为 tem_4

解决办法?不要为此使用宏。相反,请使用数组。

  data new;
     set set1;
     total = 0;
     array tem[&counter.] tem_1-tem_&counter.;
     a = 1;
     do i = 1 to &counter; *or do i = 1 to dim(tem);
       total = total + Tem[i];
     end;
 run;

当然也可以直接求和。

data new;
  set set1;
  total = sum(of tem_1-tem_4);
run;

如果您真的喜欢宏变量,您当然可以在 do 循环中执行此操作,尽管 推荐这个目的是因为坚持使用数据步骤技术真的更好。但是,无论如何,如果您在宏中 运行 this(这在开放代码中无效)。

  data new;
     set set1;
     total = 0;
     %do i = 1 %to &counter;
       total = total + Tem_&i.;         
     %end;
  run;