一起來學(xué)SAS PDV!

?初學(xué)SAS的時候,往往注重程序語法結(jié)構(gòu),而忽略了SAS編譯和執(zhí)行階段如何處理數(shù)據(jù)。所以很多時候,寫的程序看起來沒有問題,但是創(chuàng)建出的數(shù)據(jù)集觀測數(shù)和預(yù)期的卻不一致,一些變量也沒有按照預(yù)期retain下來,嘗試另起一個data步或者用一個新變量名問題就解決了,但是究竟問題出在哪里,也無從得知。今天就一起研究下SAS處理數(shù)據(jù)的機制吧!?

SAS data步包含包含兩個階段:

  • 編譯階段
  • 執(zhí)行階段

編譯階段

這個階段sas主要做:

  1. 掃描code是否存在語法錯誤;
  2. 結(jié)束后創(chuàng)建數(shù)據(jù)集的描述信息;
  3. 會產(chǎn)生兩個對象:input buffer(輸入緩沖區(qū))、PDV(program data vector)

具體講,就是確保program滿足語法規(guī)則,例如sas數(shù)據(jù)集、變量名命名規(guī)則,關(guān)鍵拼寫是否有誤,引號括號不配對,每個語句是否以分號結(jié)束等等。編譯階段完成之后,sas數(shù)據(jù)集的描述信息就創(chuàng)建好了,例如變量名、變量屬性。

語法錯誤核查完之后,SAS會創(chuàng)建input buffer(只在讀取raw data時產(chǎn)生)。input buffer只是一個邏輯概念,并沒有實際的物理儲存位置,可以理解為一個臨時儲存記錄的位置。

input buffer創(chuàng)建之后,PDV也隨著創(chuàng)建,和input buffer類似,PDV也是一個邏輯概念。

PDV的變量:data步中的所有變量,以及自動生成的變量 by-group創(chuàng)建的變量,選項生成的變量等等。

variables description
_n_ Data步執(zhí)行次數(shù)的計數(shù)變量
_error_ 錯誤信息 表示當(dāng)前觀測執(zhí)行時發(fā)生了錯誤
first.variable 同一by組第一個觀測
last.variable 同一by組最后一個觀測
_all_ 所有變量
indsname= 數(shù)據(jù)集名稱
nobs= 數(shù)據(jù)集總觀測數(shù)
curobs= 數(shù)據(jù)集當(dāng)前觀測數(shù)
end= 布爾值 最后一個數(shù)據(jù)集最后一條觀察為1,否則為0
in= 布爾值 可以標識數(shù)據(jù)集
point= 取指定觀測 等號右邊為變量 不能設(shè)置為數(shù)字 需和stop連用

執(zhí)行階段

創(chuàng)建數(shù)據(jù)部分,_N_初始化為1,_ERROR_初始化為0,F(xiàn)irst.var, Last.var初始化為1,其它的自動變量為缺失。

input語句執(zhí)行,將raw data第一行copy進input buffer, 執(zhí)行其他語句,最后輸出該條觀測到數(shù)據(jù)集中,然后返回DATA步繼續(xù)執(zhí)行,讀取下一條觀測。

在執(zhí)行階段,DATA步看起來更像是一個循環(huán),讀取一行數(shù)據(jù),執(zhí)行所有語句,創(chuàng)建一行觀測記錄,并重復(fù)這個操作。每次循環(huán)就稱作一次迭代。

并非所有的語句都是在執(zhí)行階段執(zhí)行,DATA步中的語句可以分為:聲明語句、可執(zhí)行語句。聲明語句:在編譯階段就開始生效了,可以放在DATA步中的任何位置。比如LENGTH、FORMAT、LABEL、DROP、KEEP等。

可執(zhí)行語句:必須要按照預(yù)期執(zhí)行的順序進行放置,比如input之前要先infile。

example


data total_points (drop=TeamName);  
   input TeamName $ ParticipantName $ Event1 Event2 Event3;
   TeamTotal + (Event1 + Event2 + Event3);
   datalines;
Knights Sue    6  8  8
Kings Jane     9  7  8
Knights John   7  7  7
Knights Lisa   8  9  9
Knights Fran   7  6  6
Knights Walter 9  8 10
;
run;

Input Buffer


PDV


Output語句

讀進PDV的數(shù)據(jù),默認是會被output到數(shù)據(jù)集中的,這稱為隱式輸出。如果使用了output語句(顯式輸出)來輸出記錄,隱式輸出就不會起作用了。所以,如果使用了有條件的output語句,只有滿足的條件的記錄才會被輸出到數(shù)據(jù)集中,其它記錄不會再被默認輸出,如果不同條件的記錄要以不同的要求output到數(shù)據(jù)集,可以使用多個output語句。

Reading raw data v.s. Reading sas dataset

Raw data:每次迭代時,除了自動創(chuàng)建的變量、Retain語句中的變量、SUM語句創(chuàng)建的變量、_TEMPORARY_數(shù)組中創(chuàng)建的元素、infile/file選項中創(chuàng)建的變量,其余變量在PDV中都會被設(shè)置為缺失。

SAS data set:只在執(zhí)行的第一次迭代時將PDV中的變量置為缺失,變量將會retain值直到被新的值代替。對于不是來自input dataset而是在data步中創(chuàng)建的新變量,會在執(zhí)行的每一次迭代的開始被置空。如果想要使新創(chuàng)建的變量retain值,可以使用retain語句。

drop/keep語句和選項

drop/keep分別是刪除和保留變量

  • drop/keep語句和drop/keep選項作用在輸出數(shù)據(jù)集是一樣的;
  • drop/keep選項如果作用在輸入數(shù)據(jù)集,那么相應(yīng)drop的變量或者沒被keep的變量就不會進入PDV。當(dāng)數(shù)據(jù)列非常多的時候,在輸入數(shù)據(jù)集時就keep或者drop變量,能夠提高運行效率;
  • drop/keep同時使用,drop先起作用,然后再進行keep;如果drop和keep沖突的話(drop或者keep不存在的變量),那么SAS會報錯。

where/if

where在數(shù)據(jù)進PDV之前就進行篩選,只能篩選輸入數(shù)據(jù)集中的變量,在data步創(chuàng)建的新變量不可以篩選。

  • if是在數(shù)據(jù)讀進PDV后才進行篩選,可以篩選輸入數(shù)據(jù)集中的變量,也可以篩選在數(shù)據(jù)步創(chuàng)建的新變量。
  • 如果存在by語句,那么where是在by語句之前執(zhí)行,if語句是在by語句之后執(zhí)行。by語句可以產(chǎn)生first.var, last.var的PDV變量,所以where first.var?,if first.var?;
    where語句的優(yōu)勢就是可以提高效率,因為在讀取數(shù)據(jù)之前已經(jīng)進行篩選減小了數(shù)據(jù)量,而if是每行都讀入PDV再篩選是否輸出到數(shù)據(jù)集中。

example
數(shù)據(jù)集Long如圖:



運行如下程序:


data rewide(keep=sid programming stats english);
  format Sid Programming Stats English;
  array course{3} programming stats english;
  do i = 1 to 3;
    set long;
    course{i}=score;
    put _all_;
  end;
run;

得到的數(shù)據(jù)集Rewide如圖:



這段程序中,set語句被放置在do循環(huán)內(nèi)。set語句每次只讀取一行記錄,到run結(jié)束,返回至開頭讀取下一條記錄,循環(huán)往復(fù)。

第一條do end循環(huán)結(jié)束后,PDV會讀取三行記錄:



遇到Run;之后將當(dāng)前的PDV記錄輸出至Rewide數(shù)據(jù)集中,然后指針+1,繼續(xù)進行第二個Do end循環(huán),輸出S02的一條記錄。

當(dāng)我們對sas讀取數(shù)據(jù)階段有困惑時,可以使用put all語句,將PDV的所有變量都輸出在Log中,查看每次執(zhí)行時每個變量的賦值情況。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容