Variables 如何将变量序列(列表)传递给SAS宏
我的变量名为200701,200702,。。。截至201612年,每个包含该月的特定数字数据。如果满足以下条件,我想从中减去具体金额(变量cap_inc):Variables 如何将变量序列(列表)传递给SAS宏,variables,sas,sas-macro,Variables,Sas,Sas Macro,我的变量名为200701,200702,。。。截至201612年,每个包含该月的特定数字数据。如果满足以下条件,我想从中减去具体金额(变量cap_inc): %MACRO DeleteExc(var); DATA Working.Test; SET Working.Test; IF &var. GE cap_inc THEN &var. = SUM(&var., - cap_inc); ELSE &var. = &var.; RUN; %M
%MACRO DeleteExc(var);
DATA Working.Test;
SET Working.Test;
IF &var. GE cap_inc THEN &var. = SUM(&var., - cap_inc);
ELSE &var. = &var.;
RUN;
%MEND;
如果我只把一个月作为一个参数(例如200909),代码是有效的。。。但我想把这些变量的顺序放在这里。我尝试过像“OF _200701--OF _201612”或“OF _20:”这样的组合,但没有任何效果
我还有另一个宏,使用parmbuff参数,以“for each loop”的方式工作,例如,我可以放置更多用逗号分隔的变量
%DeleteExc(_200701, _200702, _200703)
但我仍然不能以一种方便易用的方式传递所有变量。(我不想键入所有参数,因为有120个参数)
有没有办法做到这一点?
谢谢大家! 这里有一些选择-也许有一个你还没有尝试过
data example;
array months{*} _200701-_200712 _200801-_200812 (24*1);
array underscores{*} _:;
_randomvar = 100;
s1 = sum(of _200701-_200812); /*Generates lots of notes about uninitialised variables but gives correct result*/
s2 = sum(of _200701--_200812); /*Works only if there are no rogue columns in between month columns*/
s3 = sum(of months{*}); /* Requires array definition*/
s4 = sum(of _:); /*Sum any variables with _ prefix - potentially including undesired variables*/
put (s1-s4)(=);
run;
双破折号(-)变量名称范围列表可用于指定数组中的变量。简单的迭代DO循环允许您对每个变量执行所需的操作
data want;
set have;
array month_named_variables _200701 -- _201612;
do _index = 1 to dim(month_named_variables); drop _index;
IF month_named_variables(_index) GE cap_inc THEN
month_named_variables(_index) = SUM(month_named_variables(_index), - cap_inc);
ELSE
month_named_variables(_index) = month_named_variables(_index);
end;
run;
如果数据集的名称范围内有额外变量,则仍可使用数组和非宏代码:
data want;
set have;
array nums _numeric_;
do _index = 1 to dim(nums); drop _index;
_vname = vname(nums(_index)); drop _vname;
if _vname ne: '_'
or not (2007 <= input(substr(_vname,2,4), ??4.) <= 2016)
or not (01 <= input(substr(_vname,6,2), ??2.) <= 12)
or not length(_vname) = 7
then continue;
IF nums(_index) GE cap_inc THEN
nums(_index) = SUM(nums(_index), - cap_inc);
ELSE
nums(_index) = nums(_index);
end;
run;
如果我的理解是正确的,您希望使用月份进行循环,这是关于数据中变量的,您可以设置开始日期和结束日期,然后进行循环
%macro month_loop(start,end);
%let start=%sysfunc(inputn(&start,yymmn6.));
%let end=%sysfunc(inputn(&end,yymmn6.));
%let date=&start;
%do %until (%sysfunc(indexw("&date","&end")));
%let date=%sysfunc(intnx(month,&date,1));
%let var=_%sysfunc(putn(&date,yymmn6.));
data want;
set have;
IF &var. GE cap_inc THEN &var. = SUM(&var., - cap_inc);
ELSE &var. = &var.;
run;
%end;
%mend;
%month_loop(200701,201612)
首先,如果要将列表传递到宏中,请不要使用逗号分隔列表。这只会让调用宏变得非常痛苦。您可能需要使用宏引号来隐藏逗号。或者使用
/parmbuff
选项覆盖SAS的参数处理,并添加逻辑以自行处理&syspbuff
宏变量。使用值中未使用的其他字符作为分隔符。比如说|或者^。对于变量名列表,请使用空格作为分隔符
%DeleteExc(varlist=_200701 _200702 _200703)
然后,您可以在SAS需要变量列表的任何位置使用宏变量
array in &varlist ;
total = sum(of &varlist);
现在,由于您的列表实际上是一个月列表,那么请为您的宏指定开始和结束月份,并让它为您生成列表
%macro DeleteExc(start,end);
%local i var ;
%do i=0 %to %sysfunc(intck(month,&start,&end)) ;
%let var=_%sysfunc(intnx(month,&start,&i,b),yymmn6);
IF .Z < cap_inc < &var. THEN &var. = &var - cap_inc;
%end;
%mend;
DATA Working.Test;
SET Working.Test;
%DeleteExc("01JAN2007"d,"01DEC2016"d);
RUN;
%宏DeleteExc(开始、结束);
%局部i-var;
%i=0%到%sysfunc(intck(月份、开始和结束));
%设var=%sysfunc(intnx(月、月、月、月、月),yymmn6);
如果.Z
请参见SAS宏附录中的演示宏,该附录显示了如何循环日期,也许您希望采用这种方法。
%macro DeleteExc(start,end);
%local i var ;
%do i=0 %to %sysfunc(intck(month,&start,&end)) ;
%let var=_%sysfunc(intnx(month,&start,&i,b),yymmn6);
IF .Z < cap_inc < &var. THEN &var. = &var - cap_inc;
%end;
%mend;
DATA Working.Test;
SET Working.Test;
%DeleteExc("01JAN2007"d,"01DEC2016"d);
RUN;