%SYSFUNC()包装的串联函数在遇到括号时给出错误

时间:2019-03-09 17:30:59

标签: function loops macros sas

我需要编写一个宏程序来生成移动平均值计算的列表,在该列表中,我需要像这样构造一些行:

var1_ma_past_1=mean(var1, lag1(var1), lag2(var1), lag3(var1), lag4(var1), lag5(var1));
var1_ma_past_2=mean(lag1(var1), lag2(var1), lag3(var1), lag4(var1), lag5(var1), lag6(var1));
var1_ma_past_3=mean(lag2(var1), lag3(var1), lag4(var1), lag5(var1), lag6(var1), lag7(var1));
[...]
var2_ma_past_1=mean(var2, lag1(var2), lag2(var2), lag3(var2), lag4(var2), lag5(var2));

我的示例程序是

%macro test ;
    %do i = 1 %to 5;
    %let ln&i = ;
        %do j = 1 %to 5;
            %let dml = %str(,);
            %let pos = %str(lag&i(var&j));
            %let ln&j = %sysfunc(catx(&dml, &&ln&j, &pos));
        %end;
    %end;
    /* example output */
    %put &ln1;
%mend test;
%test

&j的开始和结束值计划用参数替换。

需要&ln1

的输出
lag1(var1),lag2(var1),lag3(var1),lag4(var1),lag5(var1)

但是对于&ln2 &ln3来说不是这样(缺少lag1(varn)

lag2(var4),lag3(var4),lag4(var4),lag5(var4)
lag2(var3),lag3(var3),lag4(var3),lag5(var3)

此外,我收到大量的日志输出,内容为ERROR: Required operator not found in expression:,这是因为cats()内的括号%sysfunc()中的括号,用于复制此内容的示例宏是

%macro test2;
    %let x=meow;
    %put %sysfunc(cats(x,lag()));
%mend;
%test2

我试图用%str%superq%bquote掩盖括号,但没有一个起作用。

我想学习

  1. &ln2&ln3等输出错误的原因
  2. ERROR: Required operator not found in expression:的原因以及解决方法(或解决方法,或者在错误不严重的情况下甚至抑制错误)

谢谢。

1 个答案:

答案 0 :(得分:1)

无需在宏代码中使用CAT ...()函数。

在宏代码中连接值,您只需将它们彼此相邻地展开。 而且看起来您的逻辑正在混淆I和J计数器。

%macro test ;
%do i = 1 %to 5;
  %let list = ;
  %let dlm = ;
  %do j = 1 %to 5;
    %let list = &list.&dlm.lag&j(var&i) ;
    %let dlm = ,;
  %end;
  %put &=i &=list;
%end;
%mend test;
%test

结果:

I=1 LIST=lag1(var1),lag2(var1),lag3(var1),lag4(var1),lag5(var1)
I=2 LIST=lag1(var2),lag2(var2),lag3(var2),lag4(var2),lag5(var2)
I=3 LIST=lag1(var3),lag2(var3),lag3(var3),lag4(var3),lag5(var3)
I=4 LIST=lag1(var4),lag2(var4),lag3(var4),lag4(var4),lag5(var4)
I=5 LIST=lag1(var5),lag2(var5),lag3(var5),lag4(var5),lag5(var5)

对于您的实际问题,您可能需要创建一个宏,该宏仅返回以逗号分隔的列表作为宏调用的结果。

%macro lags(varname,first,last);
%local lag dlm;
%do lag= &first %to &last ;
  %if (&lag > 0) %then %*;&dlm.lag&lag(&varname);
  %else %*;&dlm.&varname;
  %let dlm=,;
%end;
%mend lags;

%put var1_ma_past_1=mean(%lags(var1,0,5));
%put var1_ma_past_2=mean(%lags(var1,1,6));
%put var1_ma_past_3=mean(%lags(var1,2,7));
%put var2_ma_past_1=mean(%lags(var2,0,5));

为什么会收到这些错误消息:

%sysfunc()宏函数需要尝试弄清楚像CATX()这样可以在任何一种输入类型上运行的函数的每个参数是字符还是数字。这就是参数值中的()令人困惑的原因,因为看起来您正在尝试传递数字表达式。

18    %put %sysfunc(catx(|,a(b),b));
ERROR: Required operator not found in expression: a(b)
a(b)|B
19    %put %sysfunc(catx(|,(1+2),b));
3|B

您可以在值周围使用引号,然后再删除它们(如果您的值实际上不包含引号)。

%let left=A(b);
%let right=b;
%let intermediate=%sysfunc(catx(|,"&left","&right"));
%let want=%sysfunc(compress(&intermediate,%str(%"));
%put &=want;