SAS Code

SAS 基礎程式 (13)

教學目標

初步了解 SAS 基礎程式的自訂格式基本概念。

重點概念

(請注意以下內容皆為課程心得筆記,若有不清楚的部份,建議上官方主辦的 SAS Programming 2 課程,謝謝。)

所謂格式是指輸出變數所呈現的樣式,我們除了用系統內建的格式之外,像是 $w. 、yymmdd10.、comma10.2、…等預設格式,還可以透過 PROC FORMAT 敘述自訂格式,其中格式長度主要會以標籤中最長的文字為主。

自訂格式敘述

1
2
3
PROC FORMAT;
VALUE 格式名稱 開始 標籤;
RUN;

接著如何從資料集更新為永久格式,首先必須有三個變數 Start、Label 和 FmtName ,分別代表開始、標籤和格式名稱,通常針對資料集會搭配 RETAIN 和 RENAME 敘述以利提升處理效率。當我們產生具備 Start 、 Label 和 FmtName 三個變數的資料集之後,就可以透過下述 SAS 程式將資料集更新為永久格式。

永久格式敘述

1
2
PROC FORMAT CNTLIN=資料集;
RUN;

再來我們會再透過 PROC FORMAT 敘述查看永久格式的內容是否正確,請參考下述 SAS 程式。

查看格式資訊敘述

1
2
3
PROC FORMAT LIBRARY=WORK.FORMATS FMTLIB ;
SELECT 資料集;
RUN;

以及我們還可透過 PROC CATALOG 敘述查看資料集的格式資訊。

1
2
3
PROC CATALOG CAT=函式庫.資料集;
CONTENTS;
QUIT;

此外在 SAS 中可以有巢狀格式,請注意格式會有相依關係,其中長度預設為 40。

可是如何開始使用格式,SAS 主要會先找是否為預設格式,接著找 WORK.FORMATS ,再來找LIBRARY.FORMATS ,若還找不到就不找了,所以若直接使用會發生錯誤。為了解決此問題,首先我們會透過 OPTIONS NOFMTERR; 敘述告訴 SAS 若不是預設格式或在 WORK.FORMATS 中則不要顯示錯誤,正常執行,預設為 OPTIONS FMTERR 。最後我們要透過 OPTIONS FMTSEARCH=(資料館1, 資料館2); 敘述告訴 SAS 可以從哪裡找自訂格式。

最後我們要如何管理格式,主要會透過下述 SAS 程式,當匯出格式為 SAS 資料集就能夠進行格式更新為永久格式,請注意若不指定就存在 WORK.FORMATS ,直到工作結束。

匯出格式

1
2
3
4
PROC FORMAT LIBRARY=LIBREF.CATALOG 
CNTLOUT=資料集;
SELECT 格式名稱;
RUN;

總結在商業分析中我們可以透過自訂格式的方式針對資料有不同的解釋,同時在不影響資料的情況下,直接輸出呈現至報表中,因此透過自訂格式將能夠讓我們呈現出各式各樣不同類型的報表欄位呈現方式,請注意當 FORMAT 敘述用在 DATA STEP 中時則是建立清單報表時指定格式,僅有在 PROC STEP 中當成程序時才是建立和應用自訂格式。

相關資源

SAS 基礎程式 (12)

教學目標

初步了解 SAS 基礎程式的陣列基本概念。

重點概念

(請注意以下內容皆為課程心得筆記,若有不清楚的部份,建議上官方主辦的 SAS Programming 2 課程,謝謝。)

所謂陣列是指暫時性的群組,必須要指定陣列名稱,必須全部文字或全部數值格式,只存在於 DATA STEP 中執行,此外陣列不是變數。

陣列敘述格式

1
ARRAY 陣列名稱 {個數} <$> <長度> <陣列元素>;

表示方式一

1
ARRAY Var{5} Var1-Var5;

表示方式二

1
ARRAY Var{*} Var1-Var5;

表示方式三

1
ARRAY Var{*} Var1--Var5;

表示方式四

1
ARRAY Var{*} Var:;

表示方式五

1
ARRAY Var{5}

其中 { } 也可以用大括號、中括號和小括號, {個數} 必須和陣列元素個數需要相同,否則會在編譯期間發生錯誤,以及陣列無法應用於編譯期間執行的敘述,像是 KEEP、DROP、…等敘述。此外定義陣列時不需要相似和相鄰,也能夠指定為陣列中的元素,

接著表示方式一至表示方式四主要會對應已存在的變數,而表達方式五則會因為在 PDV 中找不到變數而產生新的變數,同時設定預設值為 0,分別命名為 Var1、Var2、Var3、Var4 和 Var5,同時陣列初始值會保留至 PDV 中不會重新啟始空白或 0。

再來陣列也可以應用於加總函數中,以及透過 DIM 函數主要是回傳元素的個數,例如 DIM(Var) 的結果為 5,此外每個陣列變數預設為數值格式和長度為 8,至於 { } 括號中的變數還可以進行四則運算。

最後我們常常會在資料處理的過程中使用陣列,但是當處理完成之後就需要將陣列所產生的變數刪除,此時除了透過 DROP 敘述之外,還可以透過 TEMPORARY 選項宣告暫時性的變數欄位。

表示方式一

1
ARRAY Temp_Var{5} _TEMPORARY_(0,0,0,0,0);

表示方式二

1
ARRAY Temp_Var{5} _TEMPORARY_(0 0 0 0 0);

總結在 SAS 中的陣列宣告與使用方式相較於其它程式語言非常有彈性,主要就是將陣列指標和變數分別對應,但是請注意不能文字和數值變數同時用,一定要所有變數皆為文字,或者所有變數皆為數值。

相關資源

SAS 基礎程式 (11)

教學目標

初步了解 SAS 基礎程式如何有效透過 DO-LOOP 迴圈敘述進行重複的例行作業。

重點概念

(請注意以下內容皆為課程心得筆記,若有不清楚的部份,建議上官方主辦的 SAS Programming 2 課程,謝謝。)

在實務應用中我們經常會需要進行重複的例行作業,此時我們就會透過 DO-LOOP 迴圈敘述進行重複的例行作業,以利提升 SAS 程式的可讀性。首先我們試想客戶需要了解每年和每季存款中本金加利息的情境,假設存款有五十萬,銀行利率為 1%,請參考下述 SAS 程式。

1
2
3
4
5
6
7
8
9
10
11
DATA deposit;
AMOUNT=500000;
RATE=0.01;
Yearly+(Yearly+Amount)*Rate;
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
RUN;
PROC PRINT DATA=deposit;
RUN;

輸出結果

Obs Amount Rate Yearly Quarterly
1 500000 0.01 5000 5018.78

但是上述程式若要計算三年就會需要撰寫三次 Yearly = Amount × Rate; 敘述和十二次 Quarterly + (( Quarterly + Amount ) × Rate / 4); 敘述,此時我們就可以使用 DO-LOOP 迴圈敘述,請參考下述 SAS 程式。

1
2
3
4
5
6
7
8
9
10
11
12
13
DATA deposit;
AMOUNT=500000;
RATE=0.01;
DO n=1 TO 3;
Yearly+(Yearly+Amount)*Rate;
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
END;
RUN;
PROC PRINT DATA=deposit;
RUN;

輸出結果

Obs Amount Rate n Yearly Quarterly
1 500000 0.01 4 15150.5 15207.98

接著我們就先了解 DO-LOOP 迴圈敘述格式。

1
2
DO 索引變數=開始 TO 停止<BY 增量>;
END;

其中請注意 DO-LOOP 迴圈中的索引變數會輸出為變數,增量預設為 1 ,索引變數預設會輸出為變數,當遇到 END 時會先進行增量,因此若我們停止設為 3 ,但因為增量所以最後索引變數值為 4,並且當初始化 PDV ,執行讀取敘述時會判斷 EOF 註記是否結束,若結束就停止,若沒有就執行敘述,請參考下述 SAS 程式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DATA deposit;
AMOUNT=500000;
RATE=0.01;
DO n=1 TO 3;
Yearly+(Yearly+Amount)*Rate;
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
OUTPUT;
END;
RUN;
PROC PRINT DATA=deposit;
RUN;

輸出結果

Obs Amount Rate n Yearly Quarterly
1 500000 0.01 1 5000.0 5018.78
2 500000 0.01 2 10050.0 10087.94
3 500000 0.01 3 15150.5 15207.98

再來我們還有兩種執行 DO-LOOP 迴圈的使用方式,分別為 UNTIL 和 WHILE,所謂 UNTIL 主要是滿足條件才停止,而所謂 WHILE 主要是滿足條件才執行,請注意 DO UNTIL 是先執行再判斷條件,所以一定會執行一次,DO WHILE 是先判斷條件再執行,所以不一定會執行一次,此外 DO-LOOP 可以使用 TO 和 UNTIL 與 TO 和 WHILE 條件同時使用,會先看哪個條件先符合就停止,然而 DO-LOOP 可能會需要更進階的方式判斷,此外我們會透過 LEAVE 敘述的方式避免無窮迴圈。此外請注意在 DO-LOOP 中記得加上 OUTPUT 才能夠輸出每筆觀察值,請參考下述 SAS 程式。

DO-LOOP 迴圈 SAS 程式 (WHILE )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DATA deposit;
AMOUNT=500000;
RATE=0.01;
DO WHILE (n<3);
n+1;
Yearly+(Yearly+Amount)*Rate;
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
OUTPUT;
END;
RUN;
PROC PRINT DATA=deposit;
RUN;

DO-LOOP 迴圈 SAS 程式 (UNTIL)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DATA deposit;
AMOUNT=500000;
RATE=0.01;
DO UNTIL (n>=3);
n+1;
Yearly+(Yearly+Amount)*Rate;
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
OUTPUT;
END;
RUN;
PROC PRINT DATA=deposit;
RUN;

DO-LOOP 迴圈 SAS 程式 (LEAVE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DATA deposit;
AMOUNT=500000;
RATE=0.01;
DO;
n+1;
IF (n=3) THEN LEAVE;
Yearly+(Yearly+Amount)*Rate;
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
Quarterly+((Quarterly+Amount)*Rate/4);
OUTPUT;
END;
RUN;
PROC PRINT DATA=deposit;
RUN;

輸出結果

Obs Amount Rate n Yearly Quarterly
1 500000 0.01 1 5000.0 5018.78
2 500000 0.01 2 10050.0 10087.94
3 500000 0.01 3 15150.5 15207.98

最後我們還能夠透過巢狀 DO-LOOP 迴圈敘述簡化 SAS 程式,提高可讀性,簡單來說就是 DO-LOOP 迴圈敘述中又有 DO-LOOP 迴圈敘述,其中每個層迴圈會有各自的索引值,增量不一定要相同,請參考下述 SAS 程式。

1
2
3
4
5
6
7
8
9
10
11
12
13
DATA deposit;
AMOUNT=500000;
RATE=0.01;
DO y=1 TO 3;
Yearly+(Yearly+Amount)*Rate;
DO q=1 TO 4;
Quarterly+((Quarterly+Amount)*Rate/4);
OUTPUT;
END;
END;
RUN;
PROC PRINT DATA=deposit;
RUN;

輸出結果

Obs Amount Rate y Yearly q Quarterly
1 500000 0.01 1 5000.0 1 1250.00
2 500000 0.01 1 5000.0 2 2503.13
3 500000 0.01 1 5000.0 3 3759.38
4 500000 0.01 1 5000.0 4 5018.78
5 500000 0.01 2 10050.0 1 6281.33
6 500000 0.01 2 10050.0 2 7547.03
7 500000 0.01 2 10050.0 3 8815.90
8 500000 0.01 2 10050.0 4 10087.94
9 500000 0.01 3 15150.5 1 11363.16
10 500000 0.01 3 15150.5 2 12641.57
11 500000 0.01 3 15150.5 3 13923.17
12 500000 0.01 3 15150.5 4 15207.98

總結在 SAS 中的 DO-LOOP 迴圈非常實用,但是我們需要深入了解 WHILE 和 UNTIL 使用方式的差別,簡單來說 WHILE 不一定會執行一次,只有當條件符合才會繼續,UNTIL 一定會執行一次,只有當條件符合才會停止。之後就能透過 DO-LOOP 迴圈敘述進行重複的例行作業,以利簡化 SAS 程式,同時提高可讀性。

相關資源

SAS 基礎程式 (10)

教學目標

初步了解 SAS 基礎程式如何進行變數類型自動轉換或手動轉換。

重點概念

(請注意以下內容皆為課程心得筆記,若有不清楚的部份,建議上官方主辦的 SAS Programming 2 課程,謝謝。)

一般來說,研究人員針對收集的數據資料進行統計分析時,會遇到許多問題,針對遺漏值可以透過統計運算和數值計算相關函數解決此問題之外,在 SAS 中針對不同型態的變數會進行自動轉換,至於資料集中哪些變數是什麼類型,我們主要可以透過 SAS 程式 PROC CONTENTS DATA=資料集名稱; RUN; 在結果檢視器中按字母排序的變數與屬性清單中查看變數類型。

首先型態轉換主要可以分為自動轉換和手動轉換,簡單來說,若是要轉換為數值變數,則會使用 INPUT 函數,反之若是要轉換為文字變數,則會使用 PUT 函數,請注意若我們在 SAS 使用文字加上數字將會自動將文字轉換為數字,這部份與其它程式語言不同,例如:若敘述為 X=”123” + 456 ; 則 X 的結果為 579 。

接著針對數值自動轉換主要會發生在指定數值變數、四則運算、邏輯運算、使用函數時,請注意在 WHERE 敘述不具備有自動轉換的功能,自動轉換預設 w. 的輸入格式,所以當轉換失敗時,就會變成遺漏值。其中主要使用 INPUT 函數,其格式為 INPUT(來源文字,輸入格式)。

再來針對文字自動轉換主要會發生在指定文字變數,使用 || 和 !! 連接符號進行連接處理時,但要注意數字轉文字會有前面空白的問題發生,至於當發生自動轉換時 CAT 會自動移除前面空白,因此我們可以透過 CAT 函數避免數值轉文字前產生空白的問題,此外還需要特別注意數值轉文字其預設長度為 8。其中主要使用 PUT 函數,其格式為 PUT(文字,輸出格式)。

總結 INPUT 函數主要是轉換為數字,PUT 函數主要是轉換為文字,此外請注意因為變數格式在編譯期間就決定類型格式,所以無法在執行期間改變格式,因此若要改變變數格式,則需要透過 RENAME 選項將原始變數名稱重新命名之後,再重新指定原先的變數名稱,最後再刪除重新命名變數名稱,請注意 INPUT/PUT 敘述和 INPUT/PUT 函數用途不一樣,敘述主要是讀取或寫入資料,而函數則是轉換數值或文字資料。

相關資源

SAS 基礎程式 (9)

教學目標

初步了解 SAS 基礎程式如何有效進行統計分析。

重點概念

(請注意以下內容皆為課程心得筆記,若有不清楚的部份,建議上官方主辦的 SAS Programming 2 課程,謝謝。)

一般來說,研究人員針對收集的數據資料進行統計分析時,會遇到許多問題,尤其是在遺漏的情況發生時,若我們僅使用四則運算則會產生結果為遺漏值。

首先我們要如何計算遺漏值個數,主要可以透過 NMISS 和 CMISS 兩個函數,差別在於 NMISS 為計算數值和文字的遺漏值個數,而 CMISS 為計算數字的遺漏值數,請注意文字會先自動轉換數值,請參考下述程式。

找出遺漏值 SAS 程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DATA statistic;
INPUT Var1 $ Var2 Var3 $ Var4 $ Var5;
_CMISS_ = CMISS(Var1,Var2,Var3,Var4,Var5);
_NMISS_ = NMISS(Var1,Var2,Var3,Var4,Var5);
DATALINES;
$12,345
23456
34,567
(45,678)
56789.00
;
RUN;
PROC PRINT;
RUN;

輸出結果

Obs Var1 Var2 Var3 Var4 Var5 CMISS NMISS
1 $12,345 23456 32,567 45,678.0 56789 0 3

接著我們會透過 SUM 、 MEAN 、MIN 、 MAX 、 LARGEST、SMALLEST、ORDIANL、PCTL … 等統計函數進行統計分析,其中 N 個變數可以搭配 OF 進行操作,同時若透過常用的統計運算函數時基本上就會忽略遺漏值。請參考下表。

函數名稱 使用方式 重點概念
SUM SUM(變數1, 變數2,…) 主要是計算非遺漏值變數的加總值。
MEAN MEAN(變數1, 變數2,…) 主要是計算非遺漏值變數的平均值。
MIN MIN(變數1, 變數2,…) 主要是計算非遺漏值變數的最小值。
MAX MAX(變數1, 變數2,…) 主要是計算非遺漏值變數的最大值。
LARGEST LARGEST(N,變數1, 變數2,…) 主要是在非遺漏值變數中找第 N 大。
SMALLEST SMALLEST(N,變數1, 變數2,…) 主要是在非遺漏值變數中找第 N 小。
ORDIANL ORDIANL(N,變數1, 變數2,…) 主要是先排序之後,接著在非遺漏值變數中找第 N 大。
PCTL PCTL (N,變數1, 變數2,…) 主要是先排序之後,接著在非遺漏值變數中找百分位第 N 大,範圍為 1 至 100。

再來我們處理數值變數時,通常會用到下述常用的數值計算函數。

函數名稱 使用方式 重點概念
ROUND ROUND(變數,小數點位數) 主要是針對變數進行四捨五入,其中還能夠設定小數點位數,取得更精確的結果。
ABS ABS(變數) 主要是針對變數取得絕對值。
CEIL CEIL(變數) 主要是針對變數進行無條件進位。
FLOOR FLOOR(變數) 主要是針對變數進行無條件捨去。
INT INT(變數) 主要是針對變數進行取整數位數。
MOD MOD(變數1, 變數2) 主要是將變數1 和變數 2 相除,變數1 為被除數,變數2 為除數,取得相除之後的餘數。
EXP EXP(變數) 主要是針對變數取得指數值。
LOG LOG(變數) 主要是針對變數取得自然對數值。
LOG2 LOG2(變數) 主要是針對變數取得以 2 為底的對數值。
LOG10 LOG10(變數) 主要是針對變數取得以 10 為底的對數值。

總結我們可以透過常用的統計運算函數和數值計算函數,讓研究人員針對收集的數據資料有效的進行統計分析。

相關資源