過去已介紹檔案間沒有關鍵字將如何合併?(資料的合併)利用該程式,今日要教各位如何讀取大批命名有規律的檔。
自「全民健康保險研究資料庫」釋出後,大型資料的研究已是台灣學術研究的優勢,在國際學術期刊上已有亮麗成績,「衛生福利資料科學中心」如今亦開放健保資料庫、癌症登記檔與死亡檔的資料比對,但面對全國性的龐大資料檔,光是讀檔案的步驟,就是惱人的大工程。不用著急,也毋需土法煉鋼,今天的程式可以讓大家以後讀檔更輕鬆了。
以下將以讀取「衛生福利資料科學中心」之健保民國87-99年「門診處方及治療明細檔」為例,其中一個檔名為h_nhi_opdte8702_01。如何拆解這個檔名呢?h_nhi_opdte 在龐大的檔案群是固定的,87為年份,02為月份,01為西醫(02、03為牙醫與中醫),因此所有檔案讀進來,一年有36個檔,13年有468個檔,如何讀取這麼龐大的檔案群呢?
[程式一] 利用程式寫入3個資料檔,第一個資料檔檔名為year,僅放入民國年資料;第二個資料檔檔名為month,僅放入月份資料;第三個資料檔檔名為group,僅放入醫療型態(西醫、牙醫、中醫)資料。
[程式一]
data year;
input year $ @@;
cards;
87 88 89 90 91 92 93 94 95 96 97 98 99
;
run;
data month ;
input month $ @@;
cards;
01 02 03 04 05 06 07 08 09 10 11 12
;
run;
data group;
input group $ @@;
cards;
01 02 03
;
run;
將檔案建立後,利用SQL(結構式查詢語言)程式,可以將三個沒有關鍵字的檔案合併起來,檔名為ym,產生468筆資料檔。[見程式二]
[程式二]
proc sql;
create table ym as
select *
from year, month,group;
quit;
利用累加語法no+1,將每一筆資料編上1~468的流水號。其中,no的起始值(initial)是0,第一筆資料即為0+1=1,接下來依序為1+1、2+1、3+1…,每一個編號對應至一個年份、月份與醫療型態(西醫、牙醫、中醫)。若能將這些複雜的檔名讀取後,並轉為流水號型式的檔案,每當要取用資料檔時,就可以輕易用迴圈讀取了,在資料合併的過程,也變得相當簡單。例如以迴圈從468個檔擷取所要的特定疾病,新的資料檔的檔名為cd1-cd468,再以set cd1-cd468;語法將這468個檔案合併起來,而得到13年間所有研究所關心的特定疾病。 [見程式三]
[程式三]
data aa;
set ym;
no+1;
run;
[結果]
Obs year month group no
(no=31~468省略)
為什麼要找出檔案命名的規則呢?因為您若不找到這規則,要手工更動468次檔案名稱,才能將檔案讀取進來,而且可能一個不小心而改錯,自己也不自知,因此資料的正確性只有天知!!
[程式四]~[程式七]在語法上稱為MACRO LANGUAGE(巨集指令),它可透過產生迴圈的方式控制主要程式的運作 ,如[程式六]為研究者的主要資料處理步驟,但因相同的處理步驟會在多達468個檔案中反覆執行,這個反覆的過程唯二會改變的包括DATA 之後的新檔案的建立,以及SET後面所要讀取的468個檔。中間省略的<請自行填入資料處理步驟>通常是以IF條件句擷取特定的研究資料。
由於我們已產生一個由YEAR, MONTH, GROUP所組成的468筆檔案,每一筆代表一個檔案的組成,我們可以將每一種組成對應到一個流水號 no,並形成外部迴圈。以下為每一段程式的講解:
[程式四]的%macro是巨集指令,宣告之後將產生一個巨集變項(macro variable)叫mv的巨集 ,在這個巨集中有2個參數(parameter),x 與source,x為隨機變數,與外部迴圈有關;source對應到檔名,在程式中,參數的前面會加上"&"符號,可與SAS的一般名稱作區別。
[程式七]的%mend是巨集的結束指令,宣告巨集所包覆的主要程式結束於此,並將參數x對應到一組1~468的數值中,產生迴圈。
[程式五]的call symput('source',text)是至為關鍵的部份,它將參數source與它最終會被解開的文字串text關聯起來,而這組文字串text='c.h_nhi_opdte'||trim(year)||trim(month)||'_'||trim(group即是468個檔名的歸納式,是由連結符號”||”串連起來的,串連檔名的主要部份[c.h_nhi_opdte]與後面的YEAR, MONTH與GROUP,當迴圈讀到x=1時,會對應到no=1 (因為程式中有一段if no=&x 程式),也就是第一筆資料。這時巨集指令會將參數SOURCE解開,SOURCE的對應值是TEXT,當巨集被解開,就會將TEXT解開成c.h_nhi_opdte8701_01,因為填入的值是由if no=1所決定;其它以此類推。
[程式六]DATA的後面是新的檔名,已被命名為cd&x,&x是巨集的參數,當迴圈數為1時,新的資料即被命名為CD1;當迴圈數為468時,新的資料即被命名為CD468。SET後面所讀取的資料檔為&SOURCE ,被解開時對應到text,當這個參數被解開後就將TEXT中的YEAR, MONTH, GROUP的對應值填入,而輕鬆地讀入468個檔案。
最後透過迴圈將讀入後的新檔案命名為流水號型式,將有利於後續的資料處理。
很難懂是嗎? 巨集確實是語法中較為深奧的部份。
[程式四]
%macro mv(x);
[程式五]
data _null_;
set aa;
text='c.h_nhi_opdte'||trim(year)||trim(month)||'_'||trim(group);
if no=&x then call symput('source',text);
run;
[程式六]
data e.cd&x;
set &source;
<請自行填入資料處理步驟>
run;
[程式七]
%mend;
%macro loop;
%do x=1 %to 468;
%mv(&x);
%end;
%mend;
%loop
留言列表