在SAS中循环库

时间:2014-03-05 15:07:38

标签: loops macros sas

我有数千个文件名称CLICK,它们都位于我的linux上的不同文件夹中。我已经将每个文件夹分配给一个lib,我试图提取每个单击文件(并最终附加,而不是在下面显示的代码中)。这就是我所做的

   `%let listlib=
A B C;

%macro char_loop();
%let i=1;
%let v=%scan(&listlib,&i);
%do %while(&v ne ) ;

data click&v;
     set &v.click;
     type = &v;
run;

%let i=%eval(&i+1);
%let v=%scan(&listlib,&i);
%end;
%mend;
%char_loop;` 

然而,似乎SAS无法循环“set& v.click;”,因此正在改变lib。日志显示“WORK.ACLICK.DATA不存在”。我在这里缺少什么?

2 个答案:

答案 0 :(得分:2)

&v.是宏变量 - &启动,.终止。如果像空格或分号这样的东西使得终止发生的地方很明显,那么.就不是必需的,但它在技术上是一个组件。所以你需要

set &v..click

获得实际的时间段。

另一方面,SAS在这方面并不是很擅长。你可以更好地获取perl或类似东西以将点击文件收集到一个目录中,或者更好地将它们合并到一个文件中(我之前实际上已经使用点击流文件完成了此操作)。 SAS在打开和关闭大量单个文件方面效率不高,并且需要花费更长的时间才能完成。

在这里添加另一个答案,如果您要一次性设置它们(这是一个好主意),最好的方法可能不是宏循环。您可以更轻松地执行此操作:

*macro to define an element of the set statement;
%macro set(lib=);
&lib..click
%mend set;

*proc sql to generate a list of these calls from dictionary.tables - make sure you do not have any tables you need excluded from this, and if so use WHERE to do so;
proc sql;
select cats('%set(lib=',libname,')')
into :setlist separated by ' '
from dictionary.tables
where memname='CLICK';
quit;

*set them;
data want;
set &setlist. indsname=indsn;
type = scan(indsn,1,'.');
run;

通常,宏循环比通过常规旧数据步骤和SQL执行更复杂,更慢。 indsname适用于9.3 +。

答案 1 :(得分:2)

乔指出主要问题是缺少第二期(& v ..)

它说,如果你把它们设置在初始读取而不是随后将大量工作文件连接在一起,它应该对你来说要快一点。

这样的事情应该有效:

*******************************************************************; 
*** a few test datasets.
***   note:  I prefixed that dataset with the libname because 
***          they are all technically in the same directory
***          and to highlight the difference between &v. and &v..
*******************************************************************; 
libname a (work); 
libname b (work); 
libname c (work); 

data a.aclick; 
 do i = 1 to 10; 
  output;
 end; 
run; 

data b.bclick; 
 do j = 1 to 10; 
  output;
 end; 
run; 

data c.cclick; 
 do k = 1 to 10; 
  output;
 end; 
run; 


*** modified macro  ****;    

%macro char_loop(listlib=);
%let ListN=%eval(%length(&listlib)-%length(%sysfunc(compress(&listlib)))+1); 
data click(drop=_i);
set
    %do i=1 %to &listN ;
     %let v=%scan(&listlib,&i);
       &v..&v.click (in=&v)
     %end; 
  ; 

array _t &listlib; 
do _i= 1 to &listN; 
  if _t(_i)=1 then type=vname(_t(_i)); 
end; 
run;

%mend;
%char_loop(listlib=a b c );
proc print data=click; 
run;