LC Chien

9月 132015
 

這篇技術文件主要是在介紹在進行中介分析(mediator analysis)時,如何用拔靴法(bootstrap)計算effect size及其信賴區間。作者並提供了一個巨集程式供其他使用者方便使用。首先簡單描述一下中介效應。


假設Y是依變數而X是應變數,則X對Y的直接效應關係可以用c來表示,但另外有一個間接效應關係是要經過一個中介變數M,用axb來表示,其中a是X對M的影響,而b是M對Y的影響。因此這張圖可以用下面這兩個模型來描述:

(PS) 應當還有Y=bM

本文原作者採用Fairchild et al. (2009)*的R-square法來計算effect size:


其中,等號右邊那三個R-square依序是Y=bM, Y=bM+cX以及Y=cX的R-square。然後採用拔靴法來計算信賴區間,並且用一個名為%CI_MEDIATE的巨集程式來計算。這個巨集程式包含了下面幾個參數:

  • dataset: 資料名稱
  • y: 依變數Y的名稱
  • x: 應變數X的名稱
  • m: 中介變數M的名稱
  • nboot: 拔靴法進行的迴圈數,預設值5000,若不用預設值的話,若數值不滿1000的話,程式會自動補足跑滿1000次
  • c_i: 信賴區間的長度,從1到99,預設值是95

巨集程式的原始碼請參照原文。

原文提供了一個含有12個樣本數的小範例:


假設要跑10000次的拔靴法,並且計算effect size的99%信賴區間,則巨集程式可以寫成:

%CI_MEDIATE(dataset = example, y=outcome, x=predictor, m=mediator, nboot=10000, c_i=99);

結果如下:



從結果得知,此中介分析的effect size = -0.0105,而其99%的信賴區間為(-0.1479, 0.6358)。

原文後面還有進行一連串的模擬分析來驗證這個計算的精確度,在此不詳加描述。

* Fairchild, A. J., MacKinnon, D. P., Taborga, M. P., & Taylor, A. B. (2009). R2 effect-size measures for mediation analysis. Behavior Research Methods, 41, 486-498.

CONTACT INFORMATION 
Your comments and questions are valued and encouraged. Contact the first author at:
Merlande Petit-Bois
University of South Florida
East Fowler Ave., EDU 105
Tampa, FL 33620 S
Work Phone: (813) 974-4933
Fax: (813) 974-6126 4202
Email: mpetitbo@usf.edu
9月 082015
 
原文載點:http://support.sas.com/resources/papers/proceedings12/336-2012.pdf

幾年前曾經寫過幾篇關於介紹PROC POWER和PROC GLMPOWER功能的技術文件。本篇特地再引述一篇計算樣本的技術文件的用意是這一篇特別介紹了如何用模擬的方式來做檢定力分析(Power Analysis),尤其當模型中涉及到交互作用項時。想看原文的可以直接跳到原文的第四頁來看。

若我們要用下面這個模型來做減肥藥的分析:


其中Yweightloss是服藥後減掉的體重,Xdrug是一個二項變數(1=減肥藥, 0=安慰劑),Xcalorie是一個連續型卡路里變數。這個模型還包含四個未知參數:截距項是α,兩個獨立線性項(β1, β2)還有一個交互作用項β3。假設根據之前的研究這四個參數的估計值依序是是10, 5, -0.004, 0.0025,而卡路里變數服從一個常態分配N(2500, 1000^2),而最後面的殘差項則服從常態分配N(0, 5),最後樣本裡面約只有30%的人有服用真正的減肥藥,而另外70%的人則服用安慰劑,則可以用下面的程式來模擬一百萬筆數據:


其中前面九個%let statement是來宣告模擬樣本數,估計參數值,以及卡路里變數和殘差項的分配參數值。下面的data step則是跑了一個一百萬次的迴圈,其中用ranuni(seed)來從均勻分布U(0,1)裡面模擬一個隨機亂數,讓這個隨機亂數<0.3時則該模擬值屬於那30%的實驗組(服用減肥藥,drug=1),而其餘的則變成對照組(服用安慰劑,drug=0)。至於卡路里變數則是用其平均數加上標準差乘上一個隨機亂數來生成,但我個人認為比較快的方法是直接套用rand("Normal", &mean_cal, &sd_cal)來生成。同理,殘差項也可以用rand('Normal', 0, &sd_error)來生成。最後剩下依變數Y,則把剛剛生成的那些變數套進模型公式裡面即可生成。

接著,用一個PROC GLM來分析這一百萬筆模擬數據:


估計參數如下所示:


這個結果被一個ODS OUPUT指令另存在一個叫做pe的新檔中。最後,為了計算要多少樣本才能檢測到那個交互作用項的存在,則需要用到下面這個公式:

(PS)原文誤植。期望值裡面應該是T值而非X值。

在顯著水準95%及檢定力80%的情況下,α和β分別是0.05以及0.8,所以在雙尾檢定下,這個樣本估計程式如下所示:


其中z_alpha和z_beta是拿來計算Zα和Zβ這兩個臨界值。expected_t則是計算T值的期望值:

E(T) = |T|/N^0.5

最後便可得到


由此可知需要至少152個樣本才能檢定出那個交互作用項出來。不過根據我個人的經驗,只模擬一份資料不夠,大概模擬個一千次再來求平均所得到的樣本會比較穩健。

CONTACT INFORMATION 
Wuchen Zhao
University of Southern California Department of Preventive Medicine
Division of Biostatistics
1540 Alcazar Street
CHP 222 Los Angeles, CA 90089-9010
E-mail: zhaowuchen@gmail.com
9月 082015
 
原文載點:http://support.sas.com/resources/papers/proceedings12/336-2012.pdf

幾年前曾經寫過幾篇關於介紹PROC POWER和PROC GLMPOWER功能的技術文件。本篇特地再引述一篇計算樣本的技術文件的用意是這一篇特別介紹了如何用模擬的方式來做檢定力分析(Power Analysis),尤其當模型中涉及到交互作用項時。想看原文的可以直接跳到原文的第四頁來看。

若我們要用下面這個模型來做減肥藥的分析:


其中Yweightloss是服藥後減掉的體重,Xdrug是一個二項變數(1=減肥藥, 0=安慰劑),Xcalorie是一個連續型卡路里變數。這個模型還包含四個未知參數:截距項是α,兩個獨立線性項(β1, β2)還有一個交互作用項β3。假設根據之前的研究這四個參數的估計值依序是是10, 5, -0.004, 0.0025,而卡路里變數服從一個常態分配N(2500, 1000^2),而最後面的殘差項則服從常態分配N(0, 5),最後樣本裡面約只有30%的人有服用真正的減肥藥,而另外70%的人則服用安慰劑,則可以用下面的程式來模擬一百萬筆數據:


其中前面九個%let statement是來宣告模擬樣本數,估計參數值,以及卡路里變數和殘差項的分配參數值。下面的data step則是跑了一個一百萬次的迴圈,其中用ranuni(seed)來從均勻分布U(0,1)裡面模擬一個隨機亂數,讓這個隨機亂數<0.3時則該模擬值屬於那30%的實驗組(服用減肥藥,drug=1),而其餘的則變成對照組(服用安慰劑,drug=0)。至於卡路里變數則是用其平均數加上標準差乘上一個隨機亂數來生成,但我個人認為比較快的方法是直接套用rand("Normal", &mean_cal, &sd_cal)來生成。同理,殘差項也可以用rand('Normal', 0, &sd_error)來生成。最後剩下依變數Y,則把剛剛生成的那些變數套進模型公式裡面即可生成。

接著,用一個PROC GLM來分析這一百萬筆模擬數據:


估計參數如下所示:


這個結果被一個ODS OUPUT指令另存在一個叫做pe的新檔中。最後,為了計算要多少樣本才能檢測到那個交互作用項的存在,則需要用到下面這個公式:

(PS)原文誤植。期望值裡面應該是T值而非X值。

在顯著水準95%及檢定力80%的情況下,α和β分別是0.05以及0.8,所以在雙尾檢定下,這個樣本估計程式如下所示:


其中z_alpha和z_beta是拿來計算Zα和Zβ這兩個臨界值。expected_t則是計算T值的期望值:

E(T) = |T|/N^0.5

最後便可得到


由此可知需要至少152個樣本才能檢定出那個交互作用項出來。不過根據我個人的經驗,只模擬一份資料不夠,大概模擬個一千次再來求平均所得到的樣本會比較穩健。

CONTACT INFORMATION 
Wuchen Zhao
University of Southern California Department of Preventive Medicine
Division of Biostatistics
1540 Alcazar Street
CHP 222 Los Angeles, CA 90089-9010
E-mail: zhaowuchen@gmail.com
8月 312015
 
原文載點:http://support.sas.com/resources/papers/proceedings15/3367-2015.pdf

冒號( : )在SAS的資料處理中扮演了一個鮮為人知的角色。這一篇2015年在SAS Global Forum發表的技術文件介紹了如何適當的使用冒號在SAS程式裡面。我列了幾個一般使用者比較會用到的功能。

1) Data Name Wild Card
當一個library裡面有許多SAS資料集擁有相同的開頭檔名但有不同結尾檔名,在使用一個DATA STEP來縱向合併資料時可以用冒號來取代所有檔名。比方說若有五個資料集名為ST_FL, ST_MD, ST_TX, ST_VA, ST_WA,這五個資料很明顯的有相同的開頭檔名(ST_),但有不同的檔尾。所以在SET語法後不需要一個個把這五個資料集名稱打出來,而是用ST_:來取代。例如:

同樣的觀念也可以在使用PROC DATASETS程序刪除SAS資料集時使用。例如:

這個範例還看不出冒號的威能,但試著想說若有一千個ST_開頭的資料集,若要合併或刪除時,使用冒號就可以省下許多打字的時間。

2) Variable Name Wild Card
既然冒號可以用在資料集,則當然也可以使用在變數名。例如,變數名稱都是以sbp開頭或dbp開頭,則sbp:和dbp:就可以代表所有以sbp和dbp開頭的變數。如下所示:

基本上這種用法也可以使用在SAS函數或PROC程序裡面。比方說若要用sum( ), mean( ), max( ), min( )等函數算所有sbp開頭變數的總和或平均數以及最大最小值,抑或是要用PROC PRINT列印這些變數,則用sbp:在函數裡面或VAR語法後面就不需把所有變數一個一個打出來。如下所示:

3) Creating Macro Variables
通常在製作巨集變數時,都需要開一個DATA STEP然後用CALL SYMPUT函示來定義。但在PROC SQL程序中,我們可以直接用冒號加上巨集變數名來直接定義巨集變數,如下所示:

很明顯的:id_vit在PROC SQL裡面變成一個巨集變數來表示所有的ID,因此在其他程式就可以直接用&id_vit來呼叫出那些ID。

4) Operator Modifier
有時在大筆資料裡面有找出某些特定的數據,若沒有知道完整資訊,的確有如大海撈針。但使用冒號可以節省一些時間。比方說要找出ID開頭是字串型態的'0',則在ID=和'0'之間加上一個冒號即可:

這樣一來'012'和'007'這兩個'0'開頭的ID就被找了出來。有時候可能因為轉檔的問題,數值型的ID被轉成字串,則要找出某一區段的ID時,需要先把變數換成數值型才行。但使用冒號的話可以省去這個步驟。比方說我們要從一個三位數但卻是字串型的ID裡面列印出669~999這些數據,若是數值型ID的話可以輕鬆的用WHERE 669<=ID<=999;來列印,但在字串型ID下,直接在"<="符號後面加上冒號即可。如下所示:


5) Colon Modifier
在使用CARDS;或DATALINES;輸入資料時,我們在INPUT statement後面需要定義每個變數的名稱,屬性以及長度。每個變數預設是用空白分開,但有時候我們會遇到以其他符號(比方說逗號)分開的資料,則這可以使用DLM=來處理,可是當每一筆資料在某變數長度不一致時,特殊符號在較短的數據中會被當成資料一樣讀進去,這樣後面的變數會通通錯位,最終導致資料輸入失敗。因此若遇到這個情況,可在長度前面加上一個冒號,則SAS會自動判斷每個變數的長度,當遇到較短的數據時,SAS一讀到分隔符號,就會跳到下一個變數去讀。如下所示:

在此例中,第一個name字串變數長度為7,但第一個數據(AAAAA)長度只有5,因此需要在$7前面加上一個冒號,否則SAS會把AAAAA,M讀進name變數裡面。

6) Array Variable Name Wild Card and Array Bound Delimiter
冒號也可以用在ARRAY後面定義一場串變數名稱時。比方說我們有變數名稱從year1901到year2015,則使用短短的year:就可以替代這115個變數。如下所示:

CONTACT INFORMATION 
Jinson J. Erinjeri
The Emmes Corporation
401 N Washington St.
Rockville, MD 20850
Work Phone: 301-251-1161(x 2917)
E-mail: jerinjeri@emmes.com
Web: www.emmes.com
8月 242015
 
原文載點:http://analytics.ncsu.edu/sesug/2012/SD-06.pdf

Effect size是一種量化兩個或多個變數間關係的測度。在許多臨床試驗裡面都需要這個數據。不同的研究設計需要不同種類的Effect size,其中又以Cohen's d統計量最為流行,因為他是專門用在下面這三種的研究:(1)兩個獨立群組的試後比較; (2)一個群組內的試前試後比較; (3)兩個獨立群組的試前試後差異比較。由於SAS沒有內建任何的程序來計算Effect size,所以通常需要去找線上的計算器或者自己用Excel試算表去計算。但其實Cohen's d的公式相當簡單,裡面只有用到三種元素:各組樣本,各組平均數,各組標準差。所以我在算Cohen's d時都是自己先用PROC MEANS去算出那三個元素,然後再用PROC IML去算。2012年的SESUG發表了一篇技術文件,由兩個南佛大的人公布了一個計算Cohen's d的SAS巨集程式。

這個巨集程式名為%effect_size,其共同使用下面這幾個參數:
  • data: SAS資料名
  • idvar: ID變數名
  • groupvar: 群組變數名(必須先定義為1, 2)。若只有一組,則留空白
  • timevar: 時間變數名(例如:visit=1是試前, visit=2是試後),若無則留空白
  • respvars: 受測的反應變數(必須是連續型數值變數),如果有多個則用空白分開
  • timevar1: 時間變數中代表"試前"的數字
  • timevar2: 時間變數中代表"試後"的數字
  • cl: 信賴區間%,若是要計算95%CI,則填入0.95
有一個選擇性的參數為:

  • design: 用於單一群組試前試後比較。1表示使用

所使用的部分資料如下:


其中,ID是受測者的編號,GROUP=1是實驗組,GROUP=2是對照組,VISIT=1是試前,VISIT=2是試後,而PCL, BSI, TRGI是三種不同的實驗反應變數。

設計一:獨立兩群組試後比較


若只單純比較兩組的試後反應變數差異,則其Cohen's d可從下面這個公式計算出來:
其中分子是兩組的平均差,分母是兩組混合後的標準差,公式如下:
Cohen's d的信賴區間公式如下:
其中,Cohen's d統計量的標準差公式為:
程式範例如下:


設計二:單一群組試前試後比較


設計二的Cohen's d公式與設計一相同,但分子變成是試後平均和試前平均的差異,分母的混合標準差變成:

至於95%CI計算時需要用到的Cohen's d統計量的標準差則是:
其中r12是試前與試後的相關係數。不過在使用這個巨集程式時,則多了一個design參數來讓使用者選擇要(1)直接用原始數據來算混合標準差或者是(2)用試後減掉試前的差異來算混合標準差。程式範例如下:


設計三:獨立兩群組試前試後差異比較


此設計的Cohen's d公式如下:
同樣在這個設計下可以選用原始數據來算混合標準差(design=1)或者是用試後減掉試前的差異來算混合標準差(design=2)。

程式範例如下:


原文僅以設計二跑了一次範例資料,結果如下:


%effect_size的原始程式可詳見原文的p7-p11。

Contact Information 


Rajendra Kadel, Ph. D. Candidate of Biostatistics
University of South Florida
College of Public Health
13201 Bruce B Downs, MDC56 Tampa, Florida 33612
rkadel@health.usf.edu

Kevin E. Kip, Ph.D., FAHA
Professor and Executive Director, Research Center,
University of South Florida
College of Nursing
12901 Bruce B. Downs Blvd. Tampa, FL 33612-4476
kkip@health.usf.edu
12月 192014
 
原文載點:http://www2.sas.com/proceedings/forum2008/382-2008.pdf

在配對分析裡面,McNemar's test一直是主要被拿來使用的統計分析,但這個方法有個先天上的限制是只支援二項資料。一旦資料成為多項資料時,就必須使用Generalized McNemar's test (或稱Stuart-Maxwell test)或者是Bhapkar's test。其中,Bhapkar's test是有被SAS/STAT內的程序所支援,但Generalized McNemar's test則無。Xuezheng Sun和Zhao Yang在2008年發表了一篇技術文件裡面,敘述了如何使用既有的SAS程序來執行Bhapkar's test,並且公佈了一個自製的巨集程式來執行Generalized McNemar's test。

McNemar's test主要分析2X2的列連表,不過一旦列連表擴展為rXr (r>2)的格式,則McNemar's test就不能使用:

以下使用這個列連表當作範例:

資料輸入如下:

執行巨集方法如下:
(a) Generalized McNemar's test

語法如下:
%gMcNemart(dsin = , rowv =, colv = , count = );
。dsin = SAS資料名稱
。rowv = 行變數名
。colv = 列變數名
。count = 個數變數名稱
使用方法如下:
%gMcNemar(dsin = Vision, rowv = r, colv = c, count = count);

輸出報表如下:

其中PROBCHI下面那個數字就是p-value,因此這個例子顯示出p-value =0.0007 < 0.05,可以結論出左眼跟右眼的測量結果並沒有一致性。

這個巨集的原始碼可至原文載點內取得。

(b) Bhapkar's test

這個方法可以在PROC CATMOD程序能完成:

執行後會得到一個很短的輸出報表:

在vis後面那個p-value就是答案。跟用%gMcNemar巨集的結果其實是差不多的。

根據本人使用心得,基本上兩個方法都不錯用,但如果因為樣本稀少導致某些行或列裡面的個數全部都是0的話,則運行結果會有點問題。由於PROC CATMOD已經是編譯後的程式,所以不能去改內部的原始碼,所以必須從%gMcNemar這個巨集程式來著手。我打算有空改寫%gMcNemar來解決這個問題,若投稿到SAS Global Forum有獲得刊登的話再來分享給大家。

CONTACT INFORMATION
Your comments and questions are valued and encouraged. Contact the authors at:
Xuezheng Sun
Department of Epidemiology & Biostatistics,
University of South Carolina
Columbia, SC 29208
803-777-8907
E-mail: sun4@mailbox.sc.edu
Zhao Yang
Premier Research Group plc.
1800 Parkway Place, Suite 820
Marietta, GA 30067, USA
678-279-4848
E-mail: tonyyangsxz@gmail.edu



7月 232013
 
原文載點:http://support.sas.com/resources/papers/proceedings13/131-2013.pdf 
SAS雖然可以處理龐大的資料,可是有時候過於龐大的資料沒有辦法用電子郵件寄送,直接放在網路硬碟又很佔空間,上傳下載也花時間,所以能夠壓縮成ZIP檔相信是許多人會做的動作。一般人都是額外安裝winzip, winrar或7zip來額外處理壓縮檔案的事情,但其實在SAS內部整理完資料後就可以直接進行壓縮。以下這篇發表於SAS Global Forum 2013的技術文件就教導了如何用SAS ODS程序來製作ZIP壓縮檔案。
首先,用ODS PACKAGE來打開一個包裹處理壓縮過程。
ods package(ProdOutput) open ;
使用者必須先把這個包裹命名。本範例是用ProdOutput來命名,當然也可以取別的名字。不加也可以。原文內還有一個nopf的option在最後,但不加比較好。接著,把準備要壓縮進去的資料和路徑宣告進去:
ods package(ProdOutput) add file='路徑\檔名.sas7bdat';
或者
ods package(ProdOutput) add data=library.檔名;
如果使用者已經把SAS資料生好並存在硬碟的話,建議使用上述第一個程式碼。第二個程式碼目前經過我自己的測試還有一些問題,因為壓縮進去的SAS資料副檔名從.sas7bdat變成.sad。而這個.sad副檔名是無法轉換成.sas7bdat也沒有辦法讀取,所以儘量把完整路徑和檔名寫出來。 接著就是把壓縮檔的檔名和路徑宣告出來:
ods package(ProdOutput) publish archive properties(archive_name='壓縮檔名.zip' archive_path='壓縮路徑');
最後依照ODS慣例,必須把他用close關閉才算大功告成:
ods package(ProdOutput) close;
這個功能不只是可以壓縮資料檔,也可以壓縮SAS程式碼,output報表或者是其他繪圖程序做出來的圖形。可說是相當方便。

CONTACT INFORMATION
Your comments and questions are encouraged.
Contact the author at: Jack Hamilton jfh@acm.org
7月 232013
 
原文載點:http://support.sas.com/resources/papers/proceedings13/131-2013.pdf 
SAS雖然可以處理龐大的資料,可是有時候過於龐大的資料沒有辦法用電子郵件寄送,直接放在網路硬碟又很佔空間,上傳下載也花時間,所以能夠壓縮成ZIP檔相信是許多人會做的動作。一般人都是額外安裝winzip, winrar或7zip來額外處理壓縮檔案的事情,但其實在SAS內部整理完資料後就可以直接進行壓縮。以下這篇發表於SAS Global Forum 2013的技術文件就教導了如何用SAS ODS程序來製作ZIP壓縮檔案。
首先,用ODS PACKAGE來打開一個包裹處理壓縮過程。
ods package(ProdOutput) open ;
使用者必須先把這個包裹命名。本範例是用ProdOutput來命名,當然也可以取別的名字。不加也可以。原文內還有一個nopf的option在最後,但不加比較好。接著,把準備要壓縮進去的資料和路徑宣告進去:
ods package(ProdOutput) add file='路徑\檔名.sas7bdat';
或者
ods package(ProdOutput) add data=library.檔名;
如果使用者已經把SAS資料生好並存在硬碟的話,建議使用上述第一個程式碼。第二個程式碼目前經過我自己的測試還有一些問題,因為壓縮進去的SAS資料副檔名從.sas7bdat變成.sad。而這個.sad副檔名是無法轉換成.sas7bdat也沒有辦法讀取,所以儘量把完整路徑和檔名寫出來。 接著就是把壓縮檔的檔名和路徑宣告出來:
ods package(ProdOutput) publish archive properties(archive_name='壓縮檔名.zip' archive_path='壓縮路徑');
最後依照ODS慣例,必須把他用close關閉才算大功告成:
ods package(ProdOutput) close;
這個功能不只是可以壓縮資料檔,也可以壓縮SAS程式碼,output報表或者是其他繪圖程序做出來的圖形。可說是相當方便。

CONTACT INFORMATION
Your comments and questions are encouraged.
Contact the author at: Jack Hamilton jfh@acm.org
7月 202013
 
文章來源:http://www.ats.ucla.edu/stat/sas/library/nesug99/cc107.pdf

在 SAS 裡面製作巨集變數,常用的方法不外乎是用 %let 或者是 %symput 來宣告,但功能就僅僅於此了。不過,若使用 PROC SQL 程序來宣告巨集變數的話,可以做些變化來提升程式寫作效率。
假設有一筆資料裡面內涵四個九位數字的社會安全碼(SSN),如下所示:

data ssn_list;
input ssn @@;
datalines;
123456789 234567890 345678901 456789012
;
run;
則之後想要使用這個社會安全碼變數,在 PROC SQL 底下是這樣宣告的:

proc sql noprint;
select ssn into :ssnok 
separated by ' '
from ssn_list;
quit;
其中,ssn 被定義成一個巨集變數名叫 ssnok,因此在別的程序裡面,我們可以任意使用 &ssnok 來呼叫這個變數的內容。但特別注意的有兩點,一是必須要用 separated by ' ' 來把這四個社會安全碼分開,如果沒有加上這一行,則呼叫 &ssnok 只會顯示出第一組號碼,亦即 123456789。此外,凡是被宣告成巨集變數,則預設的字串長度會被設定為八碼。若超過八碼,則會自動以科學符號表示。所謂的科學符號,就如下所示:

1.2346E8 2.3457E8 3.4568E8 4.5679E8

但若在 PROC SQL 內先定義好巨集變數的長度的話,這個問題就解決了:

proc sql noprint;
select ssn format 9. into :ssnok 
separated by ' '
from ssn_list;
quit;

因此,我們可以用 separated by 這個功能,幫忙縮短程式寫作。比方說,我們打算在另一個 data step 裡面加上下面這個 if-then 條件式:

if ssn ne 123456789 and 
 ssn ne 234567890 and 
 ssn ne 345678901 and 
 ssn ne 456789012 then return;

這個條件式很明顯的有幾個字在這些社會安全碼裡面重複出現,也就是 and ssn ne 這三個字。所以我們可以用 PROC SQL 的 separated by 把這些字自動安插進去:

proc sql noprint;
select ssn format=9. into :ssnok
separated by ' and ssn ne '
from ssn_list;
quit;

用 %put &ssnok; 就會在 log 視窗顯示:

123456789 and ssn ne 234567890 and ssn ne 345678901 and ssn ne 456789012

換句話說,原本用空格來分隔這巨集變數 ssnok 所內含的四個社會安全碼,但空格被 and ssn ne 這三個字取代了。接下來就可以在 data step 使用這個巨集變數:

data selected;
input @1 ssn @;
if ssn not eq &ssnok then return;
input <list of variables>;
output;
run;

紅色這短短的一行就是之前那一串很長的 if-then 條件式。所以當 if 條件越多時,用 PROC SQL 定義巨集變數的效果會更強大。如果 ssn 本來是文字型變數的話,if-then 條件式必須要加上『上引號』(" "),而我們只要在 PROC SQL 裡面把 ssn 放在一個 quote( ) 函數裡面即可。如下所示:

proc sql noprint;
select quote(ssn) into :ssnok
separated by ' and ssn ne '
from ssn_list;
quit;

由於文字型變數沒有變成科學符號的問題,所以 format = 9. 可以拿掉。因此,在 log 視窗列印出來會變成:

%put &ssnok;
"123456789" and ssn ne "234567890" and ssn ne "345678901" and ssn ne "456789012"
1月 011970
 
[版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規]
1.不回覆私底下email的問題。有問題的請在此留言。
2.不保證能夠回答所有問題。
3.不協助debug。
4.SAS軟體本身的問題請自行聯繫SAS客服部門。

[版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規][版規]