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;