SAS宏: loop to create variables [macro/quoting problem]

标签 sas sas-macro

基本上,我正在编写一个宏,它将输入表、输出表和变量列表作为参数。我的变量列表显示为单个参数,我使用空格字符作为分隔符。 我的宏应该将我的列表分成 nbvar 宏变量,其中将包含我的 (SAS) 变量的名称。然后,我使用数据步骤将我的 (SAS) 变量从原始字符格式输入为数值。

这是我的代码:

%macro convert_car_to_num(input,output,listvar);

/* First I split my list into nbvar variables named var&i
%qscan to avoid macro resolution of names, not really necessary here
but still works fine. My delimiter is space character, hence 
%str( ) in the %qscan*/

%let nbvar=%sysfunc(countw(&listvar));
%do i = 1 %to &nbvar;
    %let var&i=%qscan(&listvar,&i,%str( ));
%end;

/*Here is my data step. &&var&i_num is resolved just fine*/
data &output;
set &input;
%do i = 1 %to &nbvar;
    &&var&i.._num = input(&&var&i,BEST16.);
%end;
run;

%mend;

由于 &&var&i.._num 和 &&var&i 已解决,我希望我的代码能够正常工作,但我的日志显示:

varname_num

180

解析名称“varname”带有下划线。过了一会儿我发现:

错误 180-322:语句无效或使用顺序不正确。

这通常是分号放错位置的标准错误。但我知道我的宏变量已解决,因为 mprint 显示:

MPRINT(CONVERT_CAR_TO_NUM): varname_num = input(varname,BEST16.)

注意:由宏变量“VAR26”生成的行。

MPRINT(CONVERT_CAR_TO_NUM):运行;

其中 varname 是列表中第 26 个变量的正确名称,这表明解析效果很好。

为了让我更难以理解,我将指出同一段代码:

&&var&i.. = input(&&var&i,BEST16.);

确实可以编译,即使它最终没有得到预期的结果(变量仍然是字符)。

同样,相同的代码:

&&var&i.._num = &&var&i;

也无法编译。

我还测试了将宏变量的名称更改为 num_&&var&i 或 n&&var&i,甚至首先声明一个包含 &&var&i 的宏变量“名称”,所有这些都具有相同的效果。不选择与初始变量相同的名称似乎会导致代码显示 180 错误。

我猜问题在于尝试声明一个变量,知道我之前编写的一段类似的代码确实有效,其中数据步骤是一个比较(也将变量列表中的缺失值转换为零):

data &output;
set &input;
    %do i = 1 %to &nbvar;
        if &&var&i = . then &&var&i = 0;
    %end;
run;

但是对于同一段代码,如果我尝试创建一个新变量(同样使用任何名称),则写入:

if num_&&var&i = . then &&var&i = 0;

我发现自己的解析名称再次带有下划线,但现在指向以下错误:

错误 22-322:语法错误,需要以下之一:!、!!、&、(、*、**、+、-、/、;、<、 <=、<>、=、>、><、>=、AND、EQ、GE、GT、IN、LE、LT、MAX、MIN、NE、NG、NL、NOTIN、OR、 [、^=、{、|、||、~=。

最佳答案

这是 SAS 无法自动取消引用值的问题。我学到的规则是,如果您的 SAS 代码(由 MPRINT 显示)看起来有效,但出现错误,请尝试取消引用。

根据您的情况,更改为:

%unquote(&&var&i.._num) = input(&&var&i,BEST16.);

使代码工作。当然,根据您的评论,您可能不需要 %qscan ,它会引入有问题的引用字符。如果将其更改为 %scan,则无需 %unquote() 它,因为它一开始就不会被引用。

也同意@Foxer使用单个宏变量来存储列表中第i_th变量的方法。还建议创建这些 %local 变量以避免冲突。可能是这样的:

%macro convert_car_to_num(input,output,listvar);
  %local i vari;

  data &output;
    set &input;
    %do i = 1 %to %sysfunc(countw(&listvar,%str( )));
      %let vari=%scan(&listvar,&i,%str( ));
      &vari._num=input(&vari,best16.);
    %end;
  run;

%mend;

关于SAS宏: loop to create variables [macro/quoting problem],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41555172/

相关文章:

sas - 如何将列的值移动为新变量名?

sas - 问题输入 sas 日期作为数据线

SAS MACRO 到循环月结束日期

sas - 文字包含不匹配的引号。 (SAS)

纵向数据中无放回随机抽样

html - 在 SAS 宏变量中过去时如何保持 HTML 文本区域的布局?

sas - 使用SAS宏导入多个名称连续的txt文件

SAS 存储过程服务器与工作区服务器

regex - SAS 正则表达式匹配 1-3 位数字

sas - 这些宏参数有什么问题吗?