2008年8月14日 星期四

Adding One Value to All Observations

原文載點:http://www.nesug.info/Proceedings/nesug07/cc/cc45.pdf

由於最近在工作上太多人問到這個問題,所以我特別找出這一篇文章來說明。在 SAS 裡面,要在每筆資料後面加上一個特定值,依據資料排列格式的不同,有許多種作法。有得很簡單,只需要在 data step 加上一行即可,有得很複雜,得動用到 merge statement 或 proc sql 才能解決。這一篇在 NESUG 2007 年發表的技術文件列出了一些解法可供參考。

本例使用這個樣本資料:
data temp;
input Obs ID EARNHR @@;
cards;
1 1 .
2 2 5.75
3 3 5.75
4 4 6.30
5 5 6.75
6 6 8.00
7 7 8.25
8 8 9.60
9 9 10.05
10 10 12.80
;

如果打算算出 EARNHR 的中間值,然後讓他變成一個獨立的變數放在原資料 temp 的最後面。最常使用的方法是先使用 PROC MEANS 把中間值的結果另存到新的資料檔裡面:
proc means data = temp noprint ;
var EARNHR ;
output out = add (drop = _TYPE_ _FREQ_) median(EARNHR) = MEDIANEARNHR;
run ;

然後再用 merge 的方法放回原資料檔:
data temp3 ;
set temp ;
if _N_ = 1 then set add ;
run ;

接下來要教兩個進階用法。由於第一個方法會生出一個無用的資料檔 MEDIANEARNHR,雖然他只是放在暫存檔,關掉 SAS 後就會消失。但使用 PROC SQL 就根本連這個檔都不會產生。方法如下:
proc sql ;
select mean(EARNHR) as AVGEARNHR format = 8.2 into :MEANEARNHR
from temp ;
quit;

data temp ;
set temp ;
mean= &MEANEARNHR ;
run ;

本例改成放 EARNHR 的平均值 MEANEARNHR。先用 PROC SQL 把 AVEARNHR 算出來,放進一個叫做 MEANEARNHR 的巨集變數裡面,然後在把他命名成mean放進原來的資料內。這還有很多其他的用途。比方說如果想要挑出 EARNHR 小於平均值的樣本,則可以用這個 data step 來挑出:
data temp2 ;
set temp ;
where EARNHR lt &MEANEARNHR ;
run ;

挑出來的結果是:
Obs ID EARNHR
1 2 5.75
2 3 5.75
3 4 6.30
4 5 6.75
5 6 8.00

第三種方法則是用 SYMPUT 函式來定義巨集變數。此例,先用 PROC MEANS 去計算 EARNHR 的中間值,並存在 add2 裡面。
proc means data = temp noprint ;
var EARNHR ;
output out = add2 (drop=_TYPE_ _FREQ_) median(EARNHR) = MEDIANEARNHR;
run ;

然後開一個虛無的資料集「_null_」(這個資料連在work library都不會出現),然後把 add2 裡面的中間值變數名稱用 SYMPUT 定義成巨集變數。
data _null_ ;
set add2 ;
call symputx ('MDNEARNHR', MEDIANEARNHR) ;
run ;

最後就可以利用這個巨集變數在新的 data step 裡面做很多動作。無論是新增變數還是去挑資料都相當容易。
data temp;
set temp ;
median=&MDNEARNHR;
where EARNHR ge 0 and EARNHR lt &MDNEARNHR ;
run ;

個人傾向使用 PROC SQL 是因為他能夠減少無謂的資料檔輸出,只是需要相當熟悉他的語法才能夠用上手。

CONTACT INFORMATION
Your comments and questions are valued and encouraged. Contact the author at:
Anne W. Warren
MDRC
16 East 34th Street, 19th floor
New York, NY 10016
Work Phone: 212.340.8661
Fax: 212.684.0832
Email: anne.warren@mdrc.org
Web: www.mdrc.org

沒有留言:

張貼留言

要問問題的人請在文章下方的intensedebate欄位留言,請勿使用blogger預設的意見表單。今後用blogger意見表單留言的人我就不回應了。