本日介紹的是大批資料的匯出,且供資訊人員作為資料庫使用,若搭配網站的架設與資料查詢頁面的製作,即可完成特定資料庫的查詢網站。
為示範程式語法與說明結果,資料為範例資料,請勿引用統計結果或作其他延伸 !!
[任務說明]
先說明今日要完成的任務,資料匯出前,有10年的資料,包括2003至2012年,且有25個縣市別,為提供日後資訊人員建置資料庫,將產生250個資料檔,若再分性別,包括男性、女性、男女合計,將產生750個檔,若結合SAS的巨集指令(MACRO LANGUAGE)與ODS(OUTPUT DELIVERY SYSTEM),再將資料轉為HTML格式,將節省表格產出的時間,而HTML的表格自網站下載後,可直接貼至EXCEL中,再作後續的使用。以下要完成的任務條列如下:
1. 輸出的表格必須有表頭(TITLE),表頭需包括(1)年份、(2)縣市別代碼、(3)縣市別,以及(4)表格內容說明。
2. 清楚的變項中文說明
3. 註解要清楚明確, 其中[註1] 要說明(1)年份、(2)縣市別代碼、(3)縣市別,以及(4)每年的死亡人數。
4. 表格、表頭與註解要左靠
下表為250張表的其中一張。表中框在紅框框裡的項目是將隨(1)年份、(2)縣市別代碼、(3)縣市別,以及(4)每年的死亡人數而變動的項目,我們可以將250種狀況對應成一個編號,利用編號產生外部迴圈,每一個迴圈所代表的(1)年份、(2)縣市別代碼、(3)縣市別,以及(4)每年的死亡人數是不一樣的。但是究竟要如何完成呢?
[範例資料檔說明]
以癌症死亡資料進行資料處理與統計分析,匯出前的SUMMARY DATA(整理過的資料)有幾個欄位,包括:
1. 死亡時年份,變項名稱為DEATH_YEAR,有10年的資料,包括2003至2012年
2. 有25個縣市別代碼,變項名稱為county,包括01至25
3. 有25個縣市別,變項名稱為county_c,為各縣市的中文名稱
4.CANCER_C(癌症分類)
5. n_death(死於癌症人數)
6.p_death(死於癌症比例(%))
7.duration_month(癌症發生至死亡時間(月))
[程式一]
利用範例資料檔source計算每年各縣市的死亡人口數,以proc freqtables指令計算,並將結果存成num,以death_year, county, county_c分層計算,求得之統計量即為每年之死亡人數(count),因此檔案num中即包含以上所提之(1)年份、(2)縣市別代碼、(3)縣市別,以及(4)每年的死亡人數。最後再以no+1指令產生no變項,no即為外部迴圈所對應之編號,每一編號即一種年份、縣市別、年份等條件。
proc freq data=source noprint;
tables death_year*county*county_c/out=num(keep=death_year county county_c);
run;
data num;
set num;
no+1;
proc print data=num;
run;
[程式二]
death_1是資料檔source經過一連串的資料處理與統計分析後所產生的資料檔,為了輸出至HTML檔後,要有清楚的變項中文說明,則以label指令對變項名稱作註解,以retain指令指定輸出欄位由左至右之順序,經過處理後的資料檔為death_2。
data death_2;
retain CASITE_C
n_death p_death
du_month;
set death_1;
label
CANCER_C='癌症分類'
n_death='死於癌症人數'
p_death='死於癌症比例(%)'
duration_month='癌症發生至死亡時間(月)';
run;
[程式三]
將包含(1)年份、(2)縣市別代碼、(3)縣市別、(4)每年的死亡人數以及(5)no (即外部迴圈所對應之編號)之資料檔num合併至包含(1)CANCER_C(癌症分類)、(2)n_death(死於癌症人數)、(3)p_death(死於癌症比例(%))、(4)duration_month(癌症發生至死亡時間(月))等4個變項的資料檔death_2,事實上該檔還包含death_year(死亡年)、縣市別代碼(county)。
以下所使用的合併指令為merge,合併前要針對兩檔的關鍵變項(key variable)進行排序,關鍵變項為death_year(死亡年)、縣市別代碼(county)。
proc sort data=num;
by death_year county;
proc sort data=death_2;
by death_year county;
data death_3;
merge death_2 num;
by death_year county;
run;
[程式四]
以下為主要的匯出程式,目的為將10年的資料(包括2003至2012年),且有25個縣市別的癌症死亡人數、死亡比例與癌症發生至死亡時間(月)資料匯出,整批匯出250個資料檔。
步驟如下:
1. 建立巨集名稱(MACRO NAME)與參數(PARAMETER)
此例建立的MACRO NAME為DATA,內含3個參數,包含x, source, source1,以%macro宣告將即執行巨集指令,程式為%macro data(x,source,source1);
2. 寫一串文字,說明註解1的資料年份、縣市代碼、縣市別、以及該年該縣市的全部死亡人數,程式為
text='註1:'||trim(left(death_year))||'年「'||trim(left(county))||' '||trim(county_c)||'」死亡人數:'||trim(left(count))||'人。';
'||' 為聯結符號(Concatenate),將資料年份、縣市代碼、縣市別、該年該縣市的全部死亡人數,以及相關文字與符號串聯起來。
trim()為截尾函數,目的將資料後面的空白去除。
left()為左靠函數,目的將數值資料左靠,數值型資料在資料處理軟體中一般為右靠,在此例中,需左靠才不會在一串文字中出現空白。
3. 寫一串文字,說明表格抬頭的內容,其中年份、縣市代碼、縣市別會隨外部迴圈變動,程式為
text1=trim(left(death_year))||'年「'||trim(left(county))||' '||trim(county_c)||'」死於癌症之分佈';
這段文字也可作為之後匯出HTML時的檔名。
4. 定義參數SOURCE, SOURCE1中的250個參數,分別為VAR1~VAR250,VARX1~VARX250,程式為
source='var'||trim(left(no));
source1='varx'||trim(left(no));
5. 以call symput( )將參數SOURCE與TEXT關聯起來,當SOURCE被解開,SOURCE對應到VAR1~VAR250等250個參數,當VAR1~VAR250也被解開,TEXT則對應到250個狀況,若外部迴圈的參數x指向 1,TEXT對應到VAR1,當VAR1被解開,各變項所對應的內容如後:DEATH_YEAR=2003,COUNTY='01',COUNTY_C='○○縣', COUNT(死亡人數)=2037,程式為
call symput('source',text);
6. 以call symput( )將參數SOURCE1與TEXT1關聯起來,當SOURCE1被解開,SOURCE1對應到VARX1~VARX250等250個參數,當VARX1~VARX250也被解開,TEXT1則對應到250個狀況,若外部迴圈的參數x指向 1,TEXT1對應到VARX1,當VARX1被解開,各變項所對應的內容如後:DEATH_YEAR=2003,COUNTY='01',COUNTY_C='○○縣',程式為
call symput('source1',text1);
步驟1~6完之整程式如下:
%macro data(x,source,source1);
data _null_;
set num;
text='註1:'||trim(left(death_year))||'年「'||trim(left(county))||''||trim(county_c)||'」死亡人數:'||trim(left(count))||'人。';
text1=trim(left(death_year))||'年「'||trim(left(county))||' '||trim(county_c)||'」死於癌症之分佈';
if no=&x;
source='var'||trim(left(no));
source1='varx'||trim(left(no));
call symput('source',text);
call symput('source1',text1);
run;
[程式五]
7. 以options nocenter 指令指定輸出報表左靠,因此整張表將左靠。
8. 以ods html style=sasweb指令指定輸出樣式。
9. 以ods html file="l:\&&source1..html" 指令指定輸出的HTML檔之檔名與路徑。
10. 以where no=&x指令指定輸出第幾個條件的HTML檔,其中x是巨集參數,扮演的角色是外部迴圈之隨機變數的功能,它的數值來自no,因為x是巨集參數,並非一般變數,因此在參數前加上"&"以示區隔。
11. title j=left "&&source1"指令指定輸出表格之抬頭。如前所述,source1是巨集參數,因此前面要加"&"以示區隔,但在此卻加上了2個"&"符號,其目的是為了將source1解開2次,第一次解開對應到varx1~varx250,而varx1~varX250亦是巨集參數,因此仍需被解開,一旦被解開則對應TEXT1上的250種條件,當VARX1被解開TEXT1的文字被對應成
2003年「01 ○○縣」死於癌症之分佈
12. footnote1 j=left color=black "&&source"指令指定輸出表格輸出之註解1。如前所述,source是巨集參數,因此前面要加"&"以示區隔,但在此卻加上了2個"&"符號,其目的是為了將source解開2次,第一次解開對應到var1~var250,而var1~var250亦是巨集參數,因此仍需被解開,一旦被解開則對應TEXT上的250種條件,當VAR1被解開TEXT的文字被對應成
註1:2003年「01 ○○縣」死亡人數:2037人。
13. ods html close指令指定輸出的指令到此為止。
步驟7~13完之整程式如下:
options nocenter;
ods html style=sasweb;
ods html file="l:\&&source1..html" ;
proc print label data=ll3 noobs;
var CANCER_C
n_death p_death
du_month;
where no=&x;
run;
title j=left "&&source1";
footnote1 j=left color=black "&&source";
footnote2 j=left color=black "註2:癌症的定義為原發部位癌,續發部位癌或不詳者不列入。";
footnote3 j=left color=black "註3:死於癌症比例(%): 發生癌症者中,死於癌症的比例。";
ods html close;
[程式六]
14. %mend指令說明巨集指令包覆的語法到此為止。
15. %macro loop以下的語法又自成一個巨集指令,目的在於產生外部迴圈,MACRO NAME為LOOP,%DO至END%為以參數X所產生的外部迴圈,其值由1至250。
%mend;
%macro loop;
%do x=1 %to 250;
%data(&x);
%end;
%mend;
%loop
16. title 與 footnote中的j=left指定將抬頭與註解左靠,color=black指定文字的顏色。
資料輸出狀況很多,對於複雜的巨集指令只能熟能生巧,不斷嘗試錯誤,忍受挫折,才能不斷進步,加油吧!
留言列表