2014-03-05 38 views
1

我有成千上萬的文件名CLICK,它們都駐留在我的linux上的不同文件夾中。我已將每個文件夾分配給一個庫,並且我試圖提取每個單擊文件(並最終追加,而不是下面顯示的代碼中)。這是我做了什麼在SAS中循環使用庫

`%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無法遍歷「設置& v.click;」,從而正在改變庫。日誌說「WORK.ACLICK.DATA不存在」。我在這裏錯過了什麼?

回答

2

&v.是宏變量 - &開始和.終止。 .是不必要的,如果像空格或分號之類的東西明顯表明終止發生的地方,但它在技術上是一個組件。所以你需要

set &v..click 

得到的實際時期。

另一方面,SAS在這方面並不是很擅長。你最好是獲得perl或類似的東西,將點擊文件收集到一個目錄中,或者更好地將它們合併成一個文件(我之前用clickstream文件實際完成了這一點)。 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+。

+0

感謝'indsname'選擇!尚未在文檔中注意到它!這比笨重的數組從'in'變量中構建'type'要好得多。 – user3272403

+0

@alexander如果您不熟悉,您可能需要閱讀字典表和sashelp視圖;他們可以非常有幫助。 「Dictionary.table」包含庫和數據集名稱(memname),以及指定庫中每個數據集的** Many **其他屬性。如果您預先分配了數千個庫,那麼從它們提取數據有時需要一段時間,尤其是在您使用其中一個視圖時。 這裏是9.4文檔: http://support.sas.com/documentation/cdl/en/sqlproc/65065/HTML/default/viewer.htm#n02s19q65mw08gn140bwfdh7spx7.htm – user3272403

+0

輝煌!並感謝您的額外閱讀。這非常有幫助。 – Alexander

2

喬指出,主要問題是缺少第二個時期(&訴。)

這麼說,這應該是快一點給你,如果你把它們放在最初讀而不是賺很多的工作文件以便隨後將它們連接在一起。

這樣的事情應該工作:

*******************************************************************; 
*** 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; 
+0

好主意。不過,我認爲你不需要使用宏循環;添加到我的答案顯示一個更有效的方式來做到這一點。 – Joe

+0

這太好了。完美的作品!謝謝。 – Alexander