宏变量在 sas 中的 %let 语句后未初始化

macro variable is uninitialized after %let statement in sas

我想在 SAS 中创建一些像 Excel 查找函数一样工作的东西。基本上,我设置宏变量的值 var1var2,...我想根据 ref table 找到它们的索引号。但是我在数据步骤中收到以下消息。

NOTE: Variable A is uninitialized.
NOTE: Variable B is uninitialized.
NOTE: Variable NULL is uninitialized.

当我打印变量 &num1&num2 时,我什么也没得到。这是我的代码。

data ref;
    input index varname $;
    datalines;
0 NULL
1 A
2 B
3 C
;
run;

%let var1=A;
%let var2=B;
%let var3=NULL;

data temp;
    set ref;
    if varname=&var1 then call symput('num1',trim(left(index)));
    if varname=&var2 then call symput('num2',trim(left(index)));
    if varname=&var3 then call symput('num3',trim(left(index)));
run;

%put &num1;
%put &num2;
%put &num3;

如果我在 if-then 语句中键入 varname='A',我可以获得 &num1&num2、.. 的正确值。如果我随后将语句改回 varname=&var1,我仍然可以获得所需的输出。但为什么会这样呢?我不想每次都输入实际的字符串值,然后将其改回宏变量来获取结果。

解决眼前问题

如果您希望 SAS 将宏变量视为字符串常量,则需要用双引号将它们括起来。否则,它将以与在您的数据步骤中找到的任何其他随机文本位相同的方式对待它们。

或者,您可以重新定义宏变量以包含引号。

作为进一步的选择,您可以使用 symgetresolve 函数,但通常不需要这些函数,除非您想创建一个宏变量并在同一数据步骤中再次使用它.如果您将它们用作双引号的替代品,它们往往会使用更多 CPU 因为默认情况下它们会每行评估一次宏变量 - 通常,宏变量仅在编译时评估一次,在您之前代码执行。

更好的方法?

对于您正在执行的那种查找,您实际上根本不需要使用数据集 - 您可以改为定义自定义格式,这使您在如何使用它方面具有更大的灵活性。例如。这会创建一个名为 lookup:

的格式
proc format;
  value lookup
  1 = 'A'
  2 = 'B'
  3 = 'C'
  other = '#N/A' /*Since this is what vlookup would do :) */
  ;
run; 

然后你可以使用这样的格式:

%let testvar = 1;
%let testvar_lookup = %sysfunc(putn(&testvar, lookup.));

或在数据步骤中:

data _null_;
  var1 = 1;
  format var1 lookup.;
  put var1=;
run;