Leo Yeh's Blog

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 程式,同時提高可讀性。

相關資源

⬅️ Go back