公告

[公告]
2014/01/17
由於已經是faculty的關係,不太有足夠時間寫部落格。因此更新的速度會相當緩慢。再加上近幾年來SAS GLOBAL FORUM沒有出現讓我覺得驚艷的技術文件,所以能分享的文章相對也減少許多。若有人推薦值得分享的SAS技術文件,請利用『問題討論區』告知。

2013/07/19
臉書留言板的功能因為有不明原因故障,因此特此移除。而intensedebate的留言板因管理不易,也一併移除。目前已經開啟內建的 G+ 留言系統,所以請有需要留言的朋友,可直接至『問題討論區』裡面留言。


2013年7月19日 星期五

CREATING MACRO VARIABLES VIA PROC SQL

文章來源:http://www.ats.ucla.edu/stat/sas/library/nesug99/cc107.pdf

在 SAS 裡面製作巨集變數,常用的方法不外乎是用 %let 或者是 %symput 來宣告,但功能就僅僅於此了。不過,若使用 PROC SQL 程序來宣告巨集變數的話,可以做些變化來提升程式寫作效率。
假設有一筆資料裡面內涵四個九位數字的社會安全碼(SSN),如下所示:

data ssn_list;
input ssn @@;
datalines;
123456789 234567890 345678901 456789012
;
run;
則之後想要使用這個社會安全碼變數,在 PROC SQL 底下是這樣宣告的:

proc sql noprint;
select ssn into :ssnok 
separated by ' '
from ssn_list;
quit;
其中,ssn 被定義成一個巨集變數名叫 ssnok,因此在別的程序裡面,我們可以任意使用 &ssnok 來呼叫這個變數的內容。但特別注意的有兩點,一是必須要用 separated by ' ' 來把這四個社會安全碼分開,如果沒有加上這一行,則呼叫 &ssnok 只會顯示出第一組號碼,亦即 123456789。此外,凡是被宣告成巨集變數,則預設的字串長度會被設定為八碼。若超過八碼,則會自動以科學符號表示。所謂的科學符號,就如下所示:

1.2346E8 2.3457E8 3.4568E8 4.5679E8

但若在 PROC SQL 內先定義好巨集變數的長度的話,這個問題就解決了:

proc sql noprint;
select ssn format 9. into :ssnok 
separated by ' '
from ssn_list;
quit;

因此,我們可以用 separated by 這個功能,幫忙縮短程式寫作。比方說,我們打算在另一個 data step 裡面加上下面這個 if-then 條件式:

if ssn ne 123456789 and 
 ssn ne 234567890 and 
 ssn ne 345678901 and 
 ssn ne 456789012 then return;

這個條件式很明顯的有幾個字在這些社會安全碼裡面重複出現,也就是 and ssn ne 這三個字。所以我們可以用 PROC SQL 的 separated by 把這些字自動安插進去:

proc sql noprint;
select ssn format=9. into :ssnok
separated by ' and ssn ne '
from ssn_list;
quit;

用 %put &ssnok; 就會在 log 視窗顯示:

123456789 and ssn ne 234567890 and ssn ne 345678901 and ssn ne 456789012

換句話說,原本用空格來分隔這巨集變數 ssnok 所內含的四個社會安全碼,但空格被 and ssn ne 這三個字取代了。接下來就可以在 data step 使用這個巨集變數:

data selected;
input @1 ssn @;
if ssn not eq &ssnok then return;
input <list of variables>;
output;
run;

紅色這短短的一行就是之前那一串很長的 if-then 條件式。所以當 if 條件越多時,用 PROC SQL 定義巨集變數的效果會更強大。如果 ssn 本來是文字型變數的話,if-then 條件式必須要加上『上引號』(" "),而我們只要在 PROC SQL 裡面把 ssn 放在一個 quote( ) 函數裡面即可。如下所示:

proc sql noprint;
select quote(ssn) into :ssnok
separated by ' and ssn ne '
from ssn_list;
quit;

由於文字型變數沒有變成科學符號的問題,所以 format = 9. 可以拿掉。因此,在 log 視窗列印出來會變成:

%put &ssnok;
"123456789" and ssn ne "234567890" and ssn ne "345678901" and ssn ne "456789012"
CODE { display: block; /* fixes a strange ie margin bug */ font-family: Courier New; font-size: 8pt; overflow:auto; background: #f0f0f0 url(http://klcintw.images.googlepages.com/Code_BG.gif) left top repeat-y; border: 1px solid #ccc; padding: 10px 10px 10px 21px; max-height:200px; height:200px; // for IE6 line-height: 1.2em; }