
How To Count the Number of Observations in SAS Data set SAS 資料集有多少筆資料?
目錄
前言
前些時候有合作伙伴在問「如何快速得知 SAS data set 的筆數」。
直覺上我們會打開 SAS data set、視窗拉到底即可以「目測」知道最後一筆的觀測數目是多少。然而,這樣看似簡單的動作會有二個問題:一是如果 data set 很高又很胖 (資料筆數多且欄位數也多) 的時候,SAS 在顯示資料時就會需要不少時間;二是如果想要檢視的 data set 不止一個而是幾十上百個時,手動方式就顯得不再直觀,而變成相當費時費力 (而且可能會看錯觀測值 +_+)。
此外,我們也經常需要檢查 SAS data set 是不是空白沒有資料的 (empty),或者在 SAS MACRO 裡,只有在 data set 不是空白的時候,我們才會告訴 SAS 進行下一個疊代的動作。
SAS 提供了一些有效率的方式可以快速檢視 data set 的筆數,一起來看看。
計算資料筆數
以下皆以 SAS 內建的資料「HEART」為例,這是來自流行病學領域著名的研究 Framingham Heart Study,內容共有 5209 筆資料及 17 個欄位。
PROC SQL with count
proc sql;
select count(*) as count_number
from SASHELP.HEART;
quit;
結果為:count_number 5209
實際時間:1.09 秒
CPU時間:0.43 秒
SAS PROC SQL 搭配 count 是最簡便方式,SAS 會回傳 data set 裡所有的觀測數目 (包括 missing data)。
然而,這是個 「效率不佳」 的方式。
PRCO SQL 會一筆筆讀取每個觀測資料,最後才依 count(*) 計算出資料筆數,當資料很大時,執行的效率就會更差。
更有效率的方式應該是直接取用 SAS data set 的資訊,而不需要一筆筆讀取資料。事實上,SAS 很貼心的已內建這樣的資訊。
對於一個 SAS data set 來說,在資料生成的時候就已經包含了二個部分的資訊,分別為:
- Descriptor Portionー包含了變項名稱長度、變項標籤資訊、資料筆數、資料生成日期等
- Data Portionー儲存資料的值

有了這個隱藏版的功能,我們可以直接取用 Descriptor Portion 的資訊來得知資料筆數。取用的方法如下:
DATA _NULL_
data _NULL_;
if 0 then set SASHELP.HEART nobs=n;
put “no. of observations =” n;
stop;
run;
log 的顯示結果為:
no. of observations =5209
實際時間:0.00 秒
CPU時間:0.00 秒
data _NULL → 引入虛擬 data set (不產生實際的 data set)
if 0 then set → if then 條件句。由於 if 0 永遠不會滿足,所以實際上也不會 set 任何 data set。整個條件句的目的是為了讓 SAS 不讀取所有的觀測值。
nobs=n → nobs 為 SAS data set 有多少筆資料。 nobs=n 把筆數的資訊存在自行指定的變項 n
stop → 防止(停止) 迴圈無限執行
由實際執時間和 CPU 時間可知,取用 SAS Descriptor Portion 的資訊比一筆筆讀取資料、再計算觀測值的速度快上許多,執行起來整個超高效率 !
除此之外,假若想把資料筆數存起來成為 SAS MACRO variable,則可以表示為:
data _NULL_;
if 0 then set SASHELP.HEART nobs=n;
call symputx(‘totobs’,n);
stop;
run;%put no. of observations= &totobs;
此時,資料筆數已存為 SAS MACRO variable,執行 %put 後顯示為:
no. of observations= 5209
call symputx(‘totobs’, n) → 在 data step 中把值存到 SAS MACRO variable 且命名為 &totobs
如同我們在 SAS Macro: Dynamic Data-Driven Programs 快速產生 SAS Macro Variable介紹過的,data step 可以執行的步驟在 PROC SQL 裡同樣可行,這裡提供不同選擇給習慣 SQL 的使用者參考。同樣利用 SAS Descriptor Portion 的資訊來獲取資料筆數。
proc sql noprint;
select nobs into :totobs separated by ‘ ‘
from dictionary.tables
where libname=’SASHELP’ and memname=’HEART’;
quit;%put no. of observations = &totobs.;
資料筆數存為 SAS MACRO variable,執行 %put 後顯示為:
no. of observations= 5209
nobs into :totobs → 將資料筆數的資訊存入 SAS MACRO variable「totobs」
dictionary.tables → sql 內建檢視data set 的功能
libname= → 指定資料夾
memname= → 指定 data set
判斷 data set 是否為空白的 (沒有觀測值)
有時候我們需要知道 data set 是不是空白的沒有資料,這時候可以來舉一反三,利用上述的語法,請 SAS 來幫我們做判斷。
data _NULL_;
if 0 then set SASHELP.HEART nobs=n;
if n = 0 then put ‘Empty dataset’; else put ‘Not empty. No. of observations = ‘ n;
stop;
run;
log 的顯示為:
Not empty. No. of observations = 5209
擷取 SAS Descriptor Portion 中 data set 資料筆數的資訊,並將資訊存在指定的變項 n。如此一來,配合 if then 條件句,就可快速判斷 data set 是否為空白資料。
結語
SAS 有許多種方式可以獲得 data set 的筆數,包括上述的 PROC SQL with count,以及本文未提及的 PROC CONTENTS、PROC DATASETS 等,都表現得效率不佳,不是最好的方式。利用 SAS Descriptor Portion 中 data set 資料筆數的資訊,可以幫助我們迅速的獲得觀測值,且不需要產生多餘的報表或耗費時間等待 SAS 讀取每一筆資料,有效提升我們的執行效率,踹起乃!