2012/1/29

用SAS Macro表列九九乘法表 (SAS Macro入門教學)

表列出九九乘法表,我認為是很棒的迴圈入門,這個迴圈概念不論是用在SAS Data Step或SAS Macro都很適合。以下用SAS Macro做個簡單的說明。

這九九乘法程式就在下面了,有興趣的人可以直接丟到SAS執行看看,結果會在LOG視窗裡面喔!(在LOG,在LOG喔!!)

%macro A99;
%do A=1 %to 9;
    %put -----A=&A.-----;
    %do B=1 %to 9;
        %let C=&A X &B;
        %let D=%eval(&A * &B);
        %put &C = &D ;
    %end;
%end;
%mend A99;

%A99;

九九乘法

我先假設讀者都沒有SAS Macro的概念好了…我自己都亂學的有點怕XD

SAS Macro為「子程式」或「副程式」的概念,因此需要給這個子程式一個名字,『A99』就是這個程式的名字。
%macro A99%mend A99 中包裹著九九乘法的的程式。

緊接要設定第一個巨集變數,巨集變數A要自動跑出1,2,3,…,8,9的數字,同樣巨集變數B也是要能跑出1…9這些數字,剩下便是把這這些數字相乘。

「%do  [1] %to [2] ;…; %end;」為設定回圈的開始,%do%to %end均為macro的語法(Statement),在[1]要放入巨集變項的名字及起使數字,如程式所寫的A=1。[2]則放入結束的數字,程式所寫的為9。而%end這是宣告這個迴圈結束,如果忘了放入%end,此迴圈程式可是會無法執行的(大家可以試試不加的後所跑出的錯誤訊息)

「%put [3] ;」,%put為將文字或巨集變項的訊息呈現於LOG視窗中。如果沒有%put這個語法幫我們把文字或結果「列印」出來,我們也就無法看到結果了。

「%put -----A=&A.-----;」只有一個是巨集變項,那就是&A,但注意看喔,對就是要很注意!對後面有一個,點的功能是將巨集變項與後面的文字做一個連結,有點像膠水一樣的功能,當然也歡迎大家嘗試把刪除後再跑跑看。
喔對了~忘了說,這一小段程式,我是希望能在看到結果時,能多分隔線,請自己試試看了喔!

「%do B=1 %to 9; 」為巨集變項專屬的迴圈。&B變項迴圈和A變項迴圈關係為,當&A變項跑出1後,&B變項會跑出1~9,接者&A變項跑出2,然後&B變項會再跑出1~9。
所以這也是為什麼「%put -----A=&A.-----;」要放在「%do B=1 %to 9; 」之前,因為我希望在&B變項跑出1~9之前就有一個分隔線。

「%let C=&A X &B; 」,%let也是SAS Macro非常常用的語法,主要是新增一個巨集變項,這裡新增一個巨集變項C,&C包含了&A的結果以及&B的結果,因此我預期的&C應該為「1 X 1」、「1 X 2」…「9 X 9」。
巨集變項其實均以文字的形式儲存資料,因此可以有空白或是其他的文字,當然也可以包含其他的巨集變項。

「%let D=%eval(&A * &B); 」同樣也是在新增巨集變項,巨集變項D就不是那麼單純做文字呈現了,這裡我希望能計算&A和&B相乘後的結果,如果沒有使用%eval巨集函數,程式只會呈現&A和&B的值喔。
%eval可做整數運算,如果有浮點運算的需求,要改用%SYSEVALF

終於要把結果都表列出來了,因此「%put &C = &D ; 」就是要來幫忙這個部分了,有點像機器人合體!把前面的東西一次組合在一起。

終於辛苦把程式寫完了,要如何執行這個SAS MACRO程式呢?
前面我們不是有把程式命名為A99,因此使用時,只要前面多一個%就可以使用了,所以執行方式為「%A99;」

如果今天我們想要的不只是九九乘法表,我想要十五乘十五的表可以嗎?
如果已經確實學會上面迴圈,就會知道只要改%do…%to…那兩個地方就好了,但其實我們把程式作一些彈性的調整,就可以「依據客戶需求」跑出所需要的乘法表了。

修改的程式如下,同時將程式命名為AXX,不過這隻程式我就不多說了,應該很容易瞭解的!

%macro AXX ( last1, last2 );
%do A=1 %to &last1 ;
    %put -----A=&A.-----;
    %do B=1 %to &last2 ;
        %let C=&A X &B;
        %let D=%eval(&A * &B);
        %put &C = &D ;
    %end;
%end;
%mend AXX;

%AXX (15,15);

%AXX (15,20);

有興趣的讀者可以參考以下這篇教學的文章,希望能對學習SAS Macro有幫助:

過年

這一個年和前一個年有什麼不同,今年是我有記憶以來,留在老家最多天的一次,或許是有比較舒適的房間了,或許是決定讓自己好好放空。

對我來說,能見到久久沒見到的三姑媽可能是最特別…最特別的事情了。總以為長大了,過了自己的生活,但我似乎忘了這位曾經花了數十年陪伴我長大的長輩。其實我沒有忘,每年都有機會遇到她,但自己也沒有很積極去做,總有一個藉口,算了下次再說吧。

下次再說吧,這是一個恐怖的想法,以為事情都會不變,腦海中浮出「下此再說吧」這種念頭,似乎是自己在逃避「死亡的恐懼」,正視死亡所發散出令人暈眩的光芒,或許會更珍惜與長輩相處的時間,與久沒相處的長輩見面或許沒有話題了,但那又如何?

2011/10/30

熱情的展現

這幾天去台中國美館,在入口處出現了一畝稻田,水稻在微風中輕輕的搖擺,真是太美了..

這一畝稻田,在展區有介紹,是一群有心人士,為了要讓民眾與土地的關係更加密切,所做的一種裝置藝術,這個基金會也不斷強調台灣糧食依靠國外進口以及;廢耕或休耕面積不斷擴大下可能帶來的危險。

DSC09251

在入口處,有另外一位阿伯,我不知道他確切的想法為何,可能是要推廣陀螺或只是單純要讓小朋友開心,但很努力的表演。

DSC09255DSC09264DSC09268DSC09272

這些人和阿伯,都用他們方式,在釋放自己的熱情,或許能或許不能改變什麼,但我覺得,他們不會後悔,會很驕傲的完成這些心願。

台灣有你們真好。

 

-----------------------------------------------(我是分隔線)------------------------------------------------

我朋友給我的回應:

「糧與田,就目前而言算是個惡性循環。農家苦,老一輩的希望子孫認真讀書,不要再做田;子孫出了農村長了視野,大多數的人都不願意再回鄉種田。老人家守了一輩子的田,地段好的賣了,沒人收購的就放著;還能種的自己下田,沒體力的、不願做的就廢耕或休耕等著領補助款。也許會有人大喊這都是政府的問題,政策的確是脫不了關係,但法令修改的速度絕對比不上人心。
台灣的米很棒,或許比起進口米來說是貴了些,但現代人米飯吃的少,我寧可多花些錢買台灣的好米。」

2011/9/27

SAS PROC SQL入門 (Part A)


本篇應該是SAS PROC SQL的入門吧?哈~ ╯﹏╰
這在裡不會產生新的資料(Data),只介紹直接在報表中呈現結果,往下看就可以理解了。

PS:此篇 SQL入門介紹,在2008年就寫好了,有點不確定當初寫這一篇的目的,不過寫都寫了,就與大家分享 ^.^。
PROC SQL指令介紹: PROC SQL常用的指令表列
PROC SQL 選項 ;
    CREATE 表格名稱 AS
    SELECT 變項(直行)
    FROM 表格名稱(資料檔名稱)
    WHERE 條件
    GROUP BY變項
    HAVING條件
    ORDER BY 變項 ;
QUIT ;



在開始之前:
在開始之前需要建立一個範例資料檔。
DATA Heart ;
SET Sashelp.Heart (obs=20);
Height=Height*2.54;
Weight=Weight*0.454;
KEEP Status Sex AgeAtStart Height Weight  Diastolic Systolic Smoking;
run;


入門的第一步:
第一步為列出特定資料檔中所有變項的值,如同PROC PRINT一般。
在SELECT後面加「星號」,代表需要列出選取資料檔所有的變項(直行)的資料。而FROM為表示要由那個「表格(Table)」或習慣稱為「資料檔(Data)」抓取所需的資料,結果列於《圖01》。
PROC SQL;
SELECT *
FROM Heart;
QUIT;
 SQL1-01 《圖01》


只選取部分變項:
如同RPCO PRINT可以透過VAR指令只選出想要表列的結果,在PROC SQL語法中,只要於SELECT後面敘述想呈現的變項即可,例如只選取Height和Weight。結果於《圖02》。
PROC SQL;
SELECT Height, Weight
FROM Heart;
QUIT;
 SQL1-02
《圖02》


建立新變項 (基本方法) …01:
在原本DATA step函數除了幾個特殊的函數外(DIFF、LAG等),大多數均可以在PROC SQL指令中使用,在SELECT敘述後直接針對變項做運算或使用函數可建立新的變項,例如建立『Height/100』,如果無在新變項後面使用AS這個指令,新變項將會無變項名稱。結果如《圖03》。
PROC SQL;
SELECT Height/100 , Weight/(Height/100)**2 AS BMI
FROM Heart;
QUIT;
 SQL1-03
《圖03》


建立新變項 (CALCULATED指令)…02:
在上面的例子中可以發現,在計算BMI時『Height/100』似乎被重複使用到了,雖然在新的程式中將『Height/100』命為『Height_m』,但我們還不能馬上使用此新變項,除非在新變項前面增加CALCULATED指令,結果於《圖04》。(用法:CALCULATED 新變項)
PROC SQL;
SELECT Height/100 AS Height_m , 
           Weight/ (CALCULATED Height_m**2) AS BMI
FROM Heart;
QUIT;
 SQL1-04
《圖04》


建立新變項 (變項分組)…03:
在建立資料的時候,依據條件將變項重新分組,是常見到的過程,在DATA step中我們會使用IF…THEN…ELSE將變項重新分組,類似的指令在PROC SQL中使用的是下列的指令。
CASE
     WHEN 條件1 THEN 結果1
     WHEN 條件2 THEN 結果2
     ELSE結果
END AS 新變項
在資料中當身高(Height) <160、160~170和≧170的分為三組,並新增一個變項Height_gr將三組身高依序命名為1、2和3,結果如《圖05》。
PROC SQL;
SELECT ID,Height,
   CASE
      WHEN 0<=Height<160 THEN 1
      WHEN Height<170 THEN 2
      WHEN Height>=170 THEN 3
      ELSE .
   END AS Height_gr
FROM Heart;
QUIT;
 SQL1-05
《圖05》


只呈現符合特定條件的資料:
在呈現資料的時候,可能只想呈現年齡≦35歲的資料,這時WHERE指令即可達到我們的目的,結果於《圖06》。
PROC SQL;
SELECT *
FROM Heart
WHERE AgeAtStart<=35;
QUIT;
SQL1-06 
《圖06》


計算分組變項的統計量:
如果要計算分組統計量我們除了使用PROC MEANS程序外,在PROC SQL程序中,可以使用GROUP BY這個指令,及在SELECT指令中配合計算統計量的函數(例如:MEAN、STD、COUNT、MAX、MIN、NMISS、STD、SUM和VAR),可達到類似的結果。在以下程式中,產生了年齡分群的變項「age_gr」,此變項將年齡分為<40和>=40兩組,然後將「age_gr」變項置於GROUP BY後面,即可依據年齡分群的結果計算統計量,其結果如《圖07》。
PROC SQL;
SELECT MEAN(Weight) as Weight_m, STD(Weight) as Weight_STD,
           MEAN(Height) as Height_m, STD(Height) as Height_STD,
           CASE
                WHEN 0<=AgeAtStart<40 THEN "年齡<40"
                WHEN AgeAtStart>=40 THEN "年齡≧40"
                ELSE ""
           END AS age_gr
FROM Heart
GROUP BY age_gr;
QUIT;
 SQL1-07
《圖07》

參考文章:
1. Katie Minten Ronk, Steve First, David Beam. An Introduction To PROC SQL. SUGI 27.
2. Kirsty Lauderdale. PROC SQL - The Dark Side of SAS? SAS Global Forum 2007.
如有誤請指教。轉載請註明來源。

2011/4/6

40人的故事

40個人只為了完成一個的故事,這時候一切還是虛構的嗎?

很瘋狂的舉止,一個小小的團隊,大部分互相之間從沒有真實的接觸,
有人是想要心中的寶物,有人想要完成遊戲, 回想起來,我自己想要的就是那個「過程」。

在遊戲中找到40人不是很困難的事情,難的是在於完成每一個關卡,
都必須長時間的準備一切,準備物資、準備默契,至要在同一個時間40人一起出現。

WOW_060429_223258


在現實團對中會出現的挑戰,在虛擬世界中也會出現,薪水(寶物)和尊重。

天下沒有不散的宴席,這個團隊還是解散了,至少我選擇脫隊了。

這一段如幻似真的故事已經很難與其他朋友敘述了,大部分的人都覺得我很荒誕。

WOW_070304_195014  WOW_060525_151232

體驗不同的生活,我很享受這一切。

2011/2/21

圓環

DSC05006

數年繞著圓環

以圖騰為目標

但永遠繞不到

圖騰終失魔力

隻身蹤入密林

不再繞圈圈後

反而顯得無助

享受林中片刻

期待陽光灑入

2011/2/5

泡溫泉

溫泉路線
台三線真是一條有趣的路線,至少這一段路很好開,有上坡有下坡,路上風景的變化也更多樣。
沒想到要去泡溫泉的地方,會經過有名的風景名勝[內灣老街],從台三轉內灣的小路,就整整塞了40分鐘吧,還好要去泡溫泉的地方在更山裡面,人不太多。
泡個10多分鐘,就上來吃吃零食聊聊天,身體涼了再繼續泡,還真的是悠閒的生活,很快2~3小時就過去了,真的是很悠哉~
回去的時候,山中小路都沒有路燈,對山勢也相當不了解,只能靠車的頭燈探路,開起來還真的有特殊的感覺。
有機會一定還會再去泡的!

2011/2/4

道路

這應該不是很聰明的決定,現在有兩條高速公路,而且要回去的方向又是反向,但決定走很久不見的省道,果然,我幾乎花比高速公路多2小時的時間到目的地。

這一段旅程上,和我記憶中的輪廓不太相同了。平面道路多了一些景色,多了一些拍照的機會。

下次再嘗試其他的路線,由不同的路線體會台灣的景色。

2011-02-02

2010/12/4

星空圖

這天晚上,走在車水馬龍的路上,抬頭看著天上僅存的幾顆星星,每晚回家都都只能看到數量稀少的星星。
身旁的朋友,靜靜的說了一聲,好美的獵戶座,讓我驚訝的看著天空,說沒有啊,在哪裡?
他朝我背後的天空說道「就在那邊,看到那三顆連星了嗎,那是獵戶的腰帶。」

阿……這讓我驚覺,原來我每天都只朝著同一個方向的星空望去,忘了身後美麗的星空依然。

真的是好美的獵戶座。

星空圖,是我小時候僅存的記憶吧,但也忘了許多,只隱約記得春季大三角,夏季大三角。

想念杉林溪天空裡那美麗的銀河。

在中央氣象局找到12月的星空圖,看到了獵戶座,找到了冬季大三角…美麗的銀河在其中流動著。

skymap12

2010/11/28

2010/11/28


這幾天整個腦袋像是被某些思緒和情緒佔滿了,連正常的工作都顯得很吃力,必須要非常勉強才能完成,星期六更是嚴重。

今天把比較重要的工作完成了一部份,給自己一點時間重新內省自己。獲得到兩個回應。

第一個是,在Facebook上看到達賴喇嘛的一段智慧之語(請見下面的英文),大略是說「當我們擁有平靜的心靈時,遇到困難的問題,也不會影響我們內在的平靜,而且能更有效率發揮人類的智慧,反之,心靈中充滿情緒時,會很困難去處理面臨的問題…」

這一段智慧的語言,的確讓我在面對煩心的狀態時,能更從容去處理手上的問題,但卻維持不久,又必須再重新提醒自己。

第二個是,我這種狀態,都已經快被自己視為病態的現象了,總是有重複的內容,在不自覺狀態下將問題轉移到某幾個方向,其中一個是感情。

不忌諱,我是處理感情上的白癡,卻常要去挑戰自己的極限,為什麼會這樣說?。

孤獨是很大的恐懼,沒想到當面對工作上的壓力(對許多人說這一點工作算什麼),卻會強化孤獨感,再將自己的孤獨感轉化到身邊人,通常這是我內心的戰鬥,旁人不見得知道。但這種的轉化,卻將壓力轉移成感情方面的困擾,天啊,這不是在拿一支大鐵鎚用力敲打自己的腳指嗎??好痛啊!!

要很細心的觀察自我內心,才能發現這微妙的互動。如同達賴說所的,當沒有平靜的心時,是無法處理問題,更無遑面對自己的內心了。


『If you have peace of mind, when you meet with problems and difficulties they won’t disturb your inner peace. You’ll be able to employ your human intelligence more effectively. But, if your mental state is disturbed, full of emotion, it is very difficult to cope with problems, because the mind that is full of emotion is⋯⋯ biased, unable to see reality. So whatever you do will be unrealistic and naturally fail.』~~~Dalai Lama