之前曾經提過一個相當強大的 text utility macro 可以批次更改大量的變數名稱,但是在使用那個程式之前,我們必須先把舊的變數名稱用一個 %let 的函數先命個名起來,之後才能將舊變數一次代入 text utility macro。可是,當舊變數高達上百甚至上千個時,怎樣將舊變數一次代入 %let 函數就變成另一個問題。比較笨一點的方法,就是把資料轉成 EXCEL 檔,則第一行會變成變數名稱,再把他全部剪下來貼到 SAS 裡面。不過 Arthur L. Carpenter 在 2005 年的 SUGI 30 就發表了一個技術文件來說明如何迅速地一次使用一串變數。
首先,得把資料裡面所有變數的相關訊息,包含變數名稱、格式和長度存出來。
proc contents data=sashelp.class noprint out=metaclass;
run;
存出來後,就可以做下列很多事情:
BUILD THE LIST IN A DATA STEP
在一個 data step 中把 metaclass 裡面的變數名稱叫出來並命名為 allvars。
%let varlist =;
data _null_;
set metaclass;
call symput('varlist',trim(resolve('&varlist'))||' '||trim(name));
run;
%put &varlist;
CREATING THE LIST WITH SQL
用 PROC SQL 把所有變數(包含名稱、長度、格式等訊息)一次叫出來,以供接下來的任何程序來使用。
proc sql noprint;
select name ,type, length
into :varlist separated by ' ',
:typlist separated by ' ',
:lenlist separated by ' '
from metaclass;
quit;
%let cntlist = &sqlobs;
%put &varlist;
%put &typlist;
%put &lenlist;
%put &cntlist;
上述程式中的 separated by 可以讓 SQL 一直加入接下來的東西,無論是變數名稱、格式或長度。如果只想抓出變數名稱,只要留下 varlist 相關的程式碼,其他諸如 typlist 和 lenlist 相關的程式碼都可以刪除。此外 cntlist 代表變數個數,其實這是巧妙的利用 &sqlobs 這個變數去自動計算的。
USING A MACRO LOOP
其實本文真正重點是這個 macro 程式碼。因為只要呼叫這個 macro,並且指定資料檔,電腦就可以自動幫你去抓該資料檔裡面所有的變數。裡面唯一要設定的變數 Dset 其實就是資料檔名稱。
%Macro GetVars(Dset) ;
%Local VarList ;
/* open dataset */
%Let FID = %SysFunc(Open(&Dset)) ;
/* If accessable, process contents of dataset */
%If &FID %Then %Do ;
%Do I=1 %To %SysFunc(ATTRN(&FID,NVARS)) ;
%Let VarList= &VarList %SysFunc(VarName(&FID,&I));
%End ;
/* close dataset when complete */
%Let FID = %SysFunc(Close(&FID)) ;
%End ;
&VarList
%Mend ;
COUNTING THE WORDS IN A LIST
這是另一個用來計算變數總數的 macro,雖然不知道其實用性,不過還是列出來。
%macro wordcount(list);
%* Count the number of words in &LIST;
%local count;
%let count=0;
%do %while(%qscan(&list,&count+1,%str( )) ne %str());
%let count = %eval(&count+1);
%end;
&count
%mend wordcount;
一個簡短範例。執行上述 macro 後再輸入下列程式碼:
%put SASHELP.CLASS has %wordcount(&varlist) variables;
則 log 視窗會出現下面結果:
86
87 %put SASHELP.CLASS has %wordcount(&varlist) variables;
SASHELP.CLASS has 5 variables
嗯~有點無聊,我覺得用 PROC CONTENTS 就可以知道變數總數了。= =
STEPPING THROUGH THE LIST USING THE %SCAN FUNCTION
這個 macro 主要是幫你產生一個新的資料夾,裡面有原來的變數(包含所有格式和長度),但是這個資料夾是空的,也就是說沒有任何觀測值在裡面。至於有什麼用呢?我也不知道,但總是有人會需要用到吧!裡面唯一的 macro 變數 dsn 是用來指定新的資料檔名稱。
%macro emptydsn(dsn);
data &dsn(keep=&varlist);
length
%do i = 1 %to &cntlist;
%scan(&varlist,&i) %if %scan(&typlist,&i)=2 %then $; %scan(&lenlist,&i)
%end;
;
stop;
run;
%mend emptydsn;
%emptydsn(dummyclass);
上述 macro 執行出來的結果,其實就和下面這個普通的 data step 所產生出來的資料檔是一樣的。好處是,使用者就不用慢慢輸入那些煩人的變數名稱、格式和長度了。
data dummyclass(keep=Age Height Name Sex Weight);
length
Age 8
Height 8
Name $ 8
Sex $ 1
Weight 8
;
stop;
run;
AUTHOR CONTACT
Arthur L. Carpenter
California Occidental Consultants
P.O. Box 430
Oceanside, CA 92085-0430
(760) 945-0613
art@caloxy.com
www.caloxy.com
You may try this rename macro
回覆刪除http://www.cpc.unc.edu/services/computer/presentations/sas_to_stata/ren_stem
Don't need %let list anymore
Thanks for such great information. Actually, from my memory, someone once showed this page to me as well. However, because this is not a SUGI technical report, I didn't post it here.
回覆刪除