日期格式 – 與 SAS DATE 一下

前言

「日期」是所有研究資料裡不可或缺的一部分,也常是不容易處理的部分。本文以 SAS 為例,列舉一些常用的日期格式及相關應用,方便我們快速有效地處理日期格式,讓人日日是好日!


什麼是 SAS 日期格式

對 SAS 來說,日期是一種「數字」格式,而這個數字的基準點是設定為「1960 年 1 月 1 日」。也就是說,以 1 天為 1 單位,在這個日期之後的 SAS 日期會存為正整數,在此之前則為負 (最早回朔至 1958 年 1 月 1 日)。

SAS 如何辨識日期

如何產生 SAS 日期格式

  • 產生讓 SAS 可以辨識的日期有許多種方式,最簡易的一種為:

date = ’11dec1992’d; /* 指定某個日期為 SAS 日期格式*/

此時 date 顯示為:12033 (也就是1960年1月1日至 1992年12月11日的間隔)

Note:
1. date7. 形式(11dec92) 或 date9. 形式(11dec1992) 皆可
2. 月份縮寫、d 皆不分大小寫
3. 優點:可直接指定所需要的日期

  • 如果想要添加今天的日期在報表或圖示上時,可簡單使用 today()date() function。

today1= today() /* SAS 自動計算1960年1月1日至今天的天數*/

today2= date() /* SAS 自動計算1960年1月1日至今天的天數*/

  • 更常見的情況是,我們有一整欄的日期資料,想要轉換成 SAS 的日期格式:

data date;
length birth_date $ 9;
input id birth_date $ checkup_date $;
datalines;
1 11DEC1992 20180916
2 20AUG1975 20170102
3 28FEB1983 20191130
4 04JUL1962 20200830
;

此時對於 SAS 來說,birth_date 和 checkup_date 都只是文字格的欄位,SAS 無法辨認他們是日期。這時候只要利用 input() 即可快速轉換成 SAS 日期格式:

data date2; set date;
birthday=input(birth_date, date9.);
checkup= input(checkup_date, yymmdd8.);
now_age=(checkup-birthday)/365.25;
run;

INPUT (欲轉換的文字格式變項, 相對應的格式)

↑↑↑可以看到,birth_date 和 checkup_date 經由 input() function 處理後,已轉換成 SAS 日期格式,可進行四則運算。

  • 如果想要知道某個 SAS 日期是哪個年月日,這時候可以簡單的使用相關的 function:

data null;
date = 12033;

yr = year(date);
mon = month(date);
d = day(date);
wk = week(date);

put yr=;
put mon=;
put d=;
put wk=;
run;

log 顯示為:
yr=1992
mon=12
d=11
wk=49

表示12033 這個 SAS 日期,實際上為 1992 年的12月11日,是該年度的第49週。


那,關於時間「間隔」呢?

實際應用上,我們常會遇到需要知道某個病人一年前的就醫情況,或手術後三個月的復原情形,如果直接加減所需要的天數是最直接的方法,但是 SAS 提供了更有效率的方法,我們以下例說明。

data period;
index_date=’20mar2020’d; /* 指定索引日期*/

one_year_before=intnx(‘year’, index_date, -1, ‘same’); /* 一年前的相同日期*/

three_month_later=intnx(‘month’, index_date, 3, ‘same’); /* 三個月後的相同日期*/

three_month_later2=intnx(‘month’, index_date, 3); /* 三個月後的該月第一天*/

put index_date=yymmdd10.;
put one_year_before=yymmdd10.;
put three_month_later=yymmdd10.;

put three_month_later2=yymmdd10.;
run;

log 顯示為:
index_date = 2020-03-20
one_year_before = 2021-03-20
three_month_later = 2020-06-20
three_month_later2 = 2021-06-01

INTNX(‘間隔單位’, 啟始日期, 增減幅度, ‘指定位置’)

間隔單位 → 想要增減的日期單位,包含 year、semiyear(半年)、QTR(季)、month、week、week6(六週) 等。需以引號標示。
啟始日期 → index_date(可自訂想要的日期變項)
增減幅度 → 想要往前或往後追朔的幅度
指定位置 → 可留白(表示為該月的第一天)。包含 Beginning (該月的第一天)、Middle (該月的月中)、End (該月的最後一天)、Same (與啟始日期同一天)。需以引號標示。

由此可知,Intnx() 可快速且正確的找出想要追查的日期,省去我們折手指的時間及可能數錯的風險。


應用日期格式在圖上

以日期 (或時間) 為橫軸的圖示是最常見的形式之一,如果資料的格式為 SAS 日期格式,沒有指定常見的日期格式,對於閱讀會產生很大的障礙。我們以虛擬的門診人次資料為例:

data clinic; input date amount;
datalines;
13148 1100
13514 2000
13879 5100
14244 2000
14609 3000
14975 3500
15340 3500
15705 6000
16070 5200
16436 3400
16801 4800
;

symbol interpol=join value=dot height=1;
proc gplot data=clinic;
plot amount*date;
title ‘Unformatted Dates of Clinic’;
run; quit;

date: 門診日期
amount: 上年度門診人次總合

↑↑↑由圖雖然可以知道每年門診人數隨著年度變化,但是 X 軸所呈現的值為 SAS 日期格式,不是一般人容易觀看的格式。在此,可利用 format 來處理:

proc gplot data=clinic;
plot amount*date;
title ‘Unformatted Dates of Clinic’;
format date date9.;
run;

format → 指定 SAS 日期格為為 date9.

↑↑↑此圖可知,X軸已轉為大家熟知 date9. 的格式,便於觀看。

如果 date9. 的日期格式在 X 軸過於擁擠,可利用 Haxis option 及 AXIS statement 來調整呈現角度:

axis1 order=(’01jan1996’d to ’01jan2006’d by year1)
value=(a=55);
proc gplot data=clinic;
plot amount*date/haxis=axis1;
title ‘Using an AXIS Statement’;
format date date9.;
run; quit;

order= →指定 X 軸的日期範圍及間隔單位
a=55 → 指定傾斜角度為 55 度


結論

SAS 在日期格式上雖然相當多樣,可符合各類型的分析需求,然而也常造成使用者的選擇困難。本文重點式介紹常用的 SAS 日期格式及其應用,讓我們在處理日期時更加方便有效。HAVE A NICE DATE (with SAS) !

如有任何問題和意見歡迎提出