公告

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

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


2007年2月24日 星期六

Slicing and Dicing the SAS Data Set


這是 William C. Murphy 於2005年的 SUGI 30 發表的一篇關於如何在 SAS 底下進行資料切割和合併的文章。由於 SAS 讀取資料是一欄一欄(column)地讀取,所以的操作也是以欄位為優先,因此當要切割或合併對象是行位(row)時,有時在沒有特定條件下來設定的話就很難用直覺的方式去處理。Howard M. Proskin 提出了幾個方法讓這類的資料處理更方便。

一般來說 SAS 是用這種方式讀取已經存在的資料:

data Out;
set Source;
run;


如果想要從某一個觀測值開始讀取的話,可用「firstobs=n」:

data Out;
set Source (firstobs=3);
run;


上述程式表示從資料 Source 的 第三筆開始讀取。

當然,想要叫他讀到某個觀測值停止的話,就用「obs=n」來界定停止點:

data Out;
set Source(firstobs=3 obs=10);
run;


THE POINT= OPTION

如果只想讀「一筆」資料,可以將 firstobs 和 obs 的參數設定成同樣的數值,不過有另外一個比較彈性的寫法,那就是使用「point」語法:

data Out;
Slice=17;
set Source point=Slice;
output;
stop;
run;


這個程式先設定一個暫時的變數叫做「Slice」,並且給定一個數值「17」給他,然後再把 Slice 給定到 point 語法。output 和 stop 這兩個語法一定要加上,因為 output 可以輸出最後的結果,而 stop 是強制結束這個程式繼續去讀下面的資料。

如果想一次讀進不連續的多筆資料,可以配合 do loop 來讀取:

data Out;
do Slice=17, 1, 23, 17, 5, 6;
set Source point=Slice;
output;
end;
stop;
run;


SAMPLING DATA SETS

想要隨機從一個很大的資料裡面抽出一些樣本的話,可以用下面這個程式:

data Sample;
do i=1 to 1000;
Slice=int(nObs*ranuni(123456789));
set BigDataSet point=Slice nobs=nObs;
output;
end;
stop;
run;


ranuni 語法可以從後面的 seed(123456789)中以均勻分配的方式生出亂數出來。

COMBINING DATA SETS


如果有兩個資料想要合併,通常會用 merge 語法:

data Medical;
merge Physical Drugs;
by Patient;
run;


但如果你某筆資料要以「一對多」的方式合併,打個比方說,假設某個資料有病人的資料,但每個病人可能會服用多種藥物,藥物資料卻是放在另一個資料裡面,此時要合併的話,光用 merge 的話 SAS 只會給你一個大大的 error。不過只要使用下面這個程式就可以輕鬆完成這種特殊情況的資料合併。

data Medical;
set Physical (rename=(Patient=tmpPatient));
do i=1 to nObs;
set Drugs nobs=nObs point=i;
if Patient=tmpPatient then output;
end;
run;


最後 William 有提供一個可以很奇怪的 macro,有興趣的人可以自己去看看。

Your comments and questions are values and encouraged. Contact the author at
William C. Murphy
Howard M. Proskin & Associates, Inc.
300 Red Creek Dr., Suite 330
Rochester, NY 14623
Phone 585-359-2420
FAX 585-359-0465
Email wmurphy@hmproskin.com or wcmurphy@usa.net
Web www.hmproskin.com
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; }