我有一个宏来查找给定数据集中的变量名称。如果缺少宏正在查找的变量名称,则缺少的变量名称将添加到表中:
%macro miss(ds, var);
%local rc dsid result;
%let dsid=%sysfunc(open(&ds));
%if %sysfunc(varnum(&dsid,&var)) > 0 %then %do;
%put &var present;
%end;
%else %do;
insert into work.compare(missing) values("&var")
%end;
%mend;
proc datasets library=work nolist nodetails;
delete compare;
run;
proc sql;
create table work.compare (missing char(15));
%miss(ctr.panup_in, u_name);
quit;
proc print noobs data=work.compare;
run;
需要针对55个不同的变量名运行此检查。目前,我只将每一个列为
%miss(ctr.panup_in, varname);
线。
出于实际原因,我想将变量列表指定为列表,例如%let dictionary = var1 var2 var3等。我现在的斗争是找到宏循环变量列表的方法。到目前为止,我所尝试过的所有内容都会导致“#st; Stament”无效"
的错误insert into work.compare(missing) values("&var")
命令。
有没有人对如何做到这一点有任何建议?
答案 0 :(得分:1)
这循环了一组变量所在的变量 用“|”分隔。可以使用任何其他分隔符 并在扫描功能中指定。
%macro loop(varlist);
%let i=1;
%do %while (%scan(&varlist, &i, |) ^=%str());
%let var=%scan(&varlist, &i, |);
%put &var;
*rest of SAS code goes here;
*Increment counter;
%let i=%eval(&i+1);
%end;
%mend;
%let temp=a|b|c|d|e;
%loop(&temp);
答案 1 :(得分:1)
你真的需要检查吗?您可以定义要删除的所有变量的零obs数据集,如果它们丢失则使用未执行的SET来包含它们。
*All variables that you might want to add;
data master0;
attrib a length=8;
attrib b length=$15;
attrib c length=$15;
stop;
call missing(of _all_);
run;
*Subset of the variable in master0;
data a;
do a = 1 to 10;
output;
end;
retain X 1;
run;
*Create new data with master + a variables;
data a_all;
set a;
if 0 then set master0;
run;
proc print;
run;
您可以使用修改来删除您不想要的变量,以便使用所有变量更新到主数据库。
*Create new data with with only wanted variables from master0;
data a_all;
stop;
set master0;
run;
data a_all;
if 0 then modify a_all;
set a;
output;
run;
答案 2 :(得分:1)
另一个选择是让你的变量存储在一个表中 - 它们可能已经存在于一个表中。也许是dictionary.columns?
事实上,你可以通过dictionary.columns简单地完成整个过程。例如:
%let varlist=name age novar;
data values_to_check;
length name $32;
do _i = 1 to countw("&varlist.");
name= scan("&varlist.",_i);
output;
end;
run;
proc sql;
create table compare as
select V.name as missing
from values_to_check V
left join
(Select * from dictionary.columns
where memname='CLASS' and libname='SASHELP') D
on upcase(V.name)=upcase(D.name)
where D.name is null
;
quit;
如果您不必创建数据集(如果它已经存在),那么这当然更容易 - 或者作为另一个数据集中存在的变量列表,或者直接通过数据线或类似物创建数据集。可能的情况是,您有一些具有此信息的数据,而不仅仅是硬编码的%let语句。
一个示例,用于标识CLASSFIT
中不在CLASS
中的变量(均位于SASHELP
库中):
proc sql;
create table compare as
select V.name as missing
from
(Select * from dictionary.columns
where memname='CLASSFIT' and libname='SASHELP') V
left join
(Select * from dictionary.columns
where memname='CLASS' and libname='SASHELP') D
on upcase(V.name)=upcase(D.name)
where D.name is null
;
quit;
答案 3 :(得分:0)
如果您真的想要一个名称不在数据集中的表,那么您可以使用数据步骤并消除使用宏或PROC SQL的复杂性。
%let ds=sashelp.class;
%let varlist=age sex gender ;
data compare;
length missing $32 ;
dsid=open("&ds");
do i=1 to countw("&varlist");
missing = scan("&varlist",i);
if not varnum(dsid,missing) then output;
end;
rc=close(dsid);
stop;
keep missing;
run;
现在,宏解决方案可能有用的地方是,如果您想传入列表并获取另一个列表,而不生成任何代码。
%macro miss(ds, varlist);
%local dsid i var result;
%let dsid=%sysfunc(open(&ds));
%if (&dsid) %then %do;
%do i=1 %to %sysfunc(countw(&varlist));
%let var=%scan(&varlist,&i);
%if not %sysfunc(varnum(&dsid,&var)) %then %let result=&result &var;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %let result=&varlist;
&result.
%mend miss;
这样你就可以在语句中间调用宏,就像函数调用一样。
%put Missing variables are: %miss(sashelp.class,age sex gender);