若想將整個欄位的資料移動到下一格,可使用函數LAG(),若想直接計算上下兩筆資料間的數值差,可使用函數DIF(),請參考以下的示範:
利用以下程式建立一個資料檔aa, 若想計算前後兩次門診的時間間隔,可直接利用dif(opd_date)計算兩次門診的時間差,若想將門診日期向下移動,可利用lag(opd_date)。
[程式一]
data aa;
input opd_date yymmdd10.;/*-門診日期-*/
lag_date=lag(opd_date);
dif_day=dif(opd_date);
format opd_date lag_date yymmdd10.;
cards;
1998-01-03
1998-02-02
1998-02-16
1998-03-16
;
proc print;
run;
[結果一]
以上介紹了如何將整個欄位的資料移動到下一格,或計算上下兩筆資料間的數值差,使用了LAG()與DIF(),但是如果資料有MISSING且資料來自不同人,程式將如何改寫?
利用以下程式建立一個資料檔aa, 檔案中有A,B兩個病人的資料,其中A有一筆門診資料是MISSING的。若想計算前後兩次門診的時間間隔,若直接利用dif(opd_date)計算兩次門診的時間差,或利用lag(opd_date)將門診日期向下移動將造成邏輯上的錯誤。(見[程式二])
本日將介紹函數: IFN()。
IFN(logical-expression, value-returned-when-true, value-returned-when-false <,value-returned-when-missing>)
[程式二]
data aa;
input id $ opd_date yymmdd10.;/*-門診日期-*/
lag_date=lag(opd_date);
format opd_date lag_date yymmdd10.;
cards;
A 1998-01-03
A 1998-02-02
A
A 1998-03-16
A 1998-03-23
B 2001-05-12
B 2001-11-14
B 2001-12-12
;
proc print;
run;
以下程式以每一個病人的ID作為判斷依據, IFN()中先限定依ID找到每一個人的第一筆資料,再將資料向下移動或與下一筆相減,當遇到門診日期MISSING則直接往下移動或與下一筆相減。
[程式三]
data bb;
set aa;
by ID;
lag_date2= ifn( first.ID , (.) , lag(opd_date) );
dif_day2=ifn( first.ID , (.) , dif(opd_date) );
format opd_date lag_date2 yymmdd10.;
proc print;
run;
[結果二]
lag_date是直接將opd_date(門診日期)向下移動,而未考慮門診日期是來自不同人的資料。lag_date2則是考慮不同人的資料後,再將opd_date向下移動。因此id='A'的患者〞之opd_date若以LAG()向下移動,則第6筆日期差欄位(dif_day)則由id='B'的第1筆opd_date與id='A'的第5筆opd_date相減,因此產生錯誤。
所以,要選擇ifn(),再將lag()包覆進去,限定每人的起始資料,以及限定遇到missing跳過。
如果在分析健保資料庫時,個人的身份必需同時考慮ID, birthday,程式可以修改如下。
[程式四]
data bb;
set aa;
by ID birthday;
lag_date2= ifn( first.ID=1 & first.birthday=1 | first.ID=0 & first.birthday=1, (.) , lag(opd_date) );
dif_day2=ifn( first.ID=1 & first.birthday=1 | first.ID=0 & first.birthday=1 , (.) , dif(opd_date) );
format opd_date lag_date2 yymmdd10.;
proc print;
run;
因為我國戶政中可能出現相同ID,卻不同人的情況,此時要將生日考慮進來,因此資料移動時的依據包括ID與生日,當ID相同時取第一筆,同時,在相同的ID下,生日也要取第一筆;若相同的ID,但生日是第一次出現,但是,是在其他筆第一次出現,表示為相同ID但不同生日的人。當定位了第一筆資料後,就可將資料往下移動一格,若想移動2格以上,或向上移動,需要利用SAS的expand程序,將以另外的專章討論。
留言列表