Function %SYSFUNC()包装的连接函数在遇到括号时出错

Function %SYSFUNC()包装的连接函数在遇到括号时出错,function,loops,macros,sas,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), l

我需要编写一个宏程序来生成移动平均值计算列表,其中我需要如下构造一些行:

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)
缺失)

此外,我得到了大量的日志输出,说
错误:在表达式中找不到必需的运算符:
,这是因为
cats()
中的括号,它位于
%sysfunc()
中,复制该表达式的示例宏是

%macro test2;
    %let x=meow;
    %put %sysfunc(cats(x,lag()));
%mend;
%test2
我试图用
%str
%superq
%bquote
来掩盖括号,但没有一个起作用

我想学习

  • &ln2
    &ln3
    等输出不正确的原因
  • 错误的原因:在表达式中找不到必需的运算符:
    以及如何修复它(或解决方法,甚至在错误不严重时抑制错误)

  • 提前感谢。

    宏代码中不需要使用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
    
    您可以强制在值周围加引号,然后稍后删除它们(如果您的值实际上不包含引号)


    您有SAS ETS许可证吗?如果是这样的话,PROC EXPAND可以以一种更简单的方式完成很多工作。您可以使用
    proc product\u status;运行
    @Reeza我担心
    PROC EXPAND
    也会包括移动平均值计算的缺失值,这是我不想要的。我还觉得每个
    PROC EXPAND
    都会输出一个数据集,在这种情况下,效率会大大降低,尽管我还没有亲自验证过。这两种担心都不正确。您可以在一次调用中进行多个计算。请澄清
    %*?它似乎消除了空格,但没有解释它是如何工作的只是一个很短的注释。这是一个宏观评论。与块注释相反,
    /***/
    ,或与语句注释相反,
    *。它所做的是消除宏生成的文本前面的空白。哇,我不知道
    %*实际上具有功能性用途。我一直认为这是各种注释方式中最糟糕的一种……您可以在宏定义中使用宏注释,当MPRINT选项打开时,它们将不会打印,而正常语句样式的注释将打印。。因此,您可以使用宏注释来帮助编码人员理解代码,并使用普通语句样式的注释来帮助用户理解日志。
    
    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;