Data Step 粗分有二種目的. A. 從一些外部的資料檔讀進成為 sas 資料檔(庫) B. 將已存在的資料檔, 做進一步的處理, 整理成為新的 sas 資料檔. 以下會分別說明.
-----------------------------------------------------------------
A. Read From external file.
infile 相關, 暫時不多寫, google 很容易可以查到資料
B. Data Processing: 在 IML 那篇提到, DATA STEP 對我極為困擾, 現在對它的機制已比較了解, 所以就想用程式語言的概念來解釋及說明它所有的行為. 也可以讓有同樣疑惑的人, 可以更深入的了解它的內部運作. 可以加速因為原理語法不了解, try and error, debug 所花的時間.
# 要了解它的運作細節, 應先去了解 PDV. (Program Data Vector). 有興趣的人可以去查這方面的資料. 這篇不從PDV 的角度去理解. 想讓大家了解, 一些語法命令寫出後, 它的等效動作.
-------------------------------------------------------------------------
data d; /* 要處理的資料*/
input id name$ vol r;
cards;
1 AABBCCDD 10 0.01
1 A 12 -0.02
1 A 9 -0.001
1 A 3 0.03
2 B 4 0.015
2 B 5 -0.021
2 B 6 -0.098
2 B 7 -0.033
8 C 1 0.033
8 C 1 0.0056
8 C 1 0.0044
;
run;
* 例1: 一個簡單的例子 ;
Data AA; * AA the new output;
set D; * D: exist file;
run; * 有run 才會執行, 不然不會有結果, 會queue 在系統中, 直到看到下一個run ;
* 以上等效是 copy d 到一個新的 file aa. ;
*-----------------------------------------;
* 例2 ;
data aa;
set d;
xxx=vol+3; * 對每個資料列, 都會產生一新的欄位 xxx 算法是從vol 欄位值加3;
data bb;
set d;
run; * 可以數個data 或其他命令 MEAN, SORT,... 可合併只用一個RUN ;
----------------------------
在這裡要開始解釋上面的寫法, DATA STEP 實際的執行動作是什麼?
用 pseudo code 來表示 例2. AA 這個例子
1. create new file "aa";
2. open "d" as input
3. suppose d 有 r 筆 (row)
4. for i=1 to r; *假設d有筆資料, 這是隱藏的迴圈, 從語法看不出來;
5. xxx[i]=vol[i]+3;
6. end.
從 4,5,6 會逐行抓取當行的資料, 可以拿來做運算. output 會增加一個欄位 xxx, 內容就是vol +3.
以上就是 data step 的基本型
3. Retain
Data aa; Set d;
retain xx 3; /* 初始值, 其實是在迴圈外設定 */
xx=xx+val;
run;
Pseudo code (Retain xx 3)
1. create new file "aa";
2. open "d" as input
3. int XX=3; * retain XX 3, 有retain在迴圈內就不再 initial ;
4. for i=1 to r
5. xx[i]=xx+vol[i]; * xx 會被累加, 最後一筆的 xx 是r 筆 vol 的總合, 再加上 initial 3 的結果 ;
6. end.
------------------
沒有 Retain
Data aa; Set d;
xx=3;
xx=xx+vol[i];
run;
Pseudo code (沒有 Retain)
1. create new file "aa";
2. open "d" as input
3. for i=1 to r
3. XX=3; /* 以上的初始值其實是設定在 迴圈內 */
5. xx[i]=vol[i]+xx; * [i] 是用來表明他是第 i 筆 xx 的輸出值, 實際上沒有 array ;
6. end.
==========================
未給初始值,沒有 Retain 時
Data aa; Set d;
if val<10 then xx=10;
run;
1. create new file "aa";
2. open "d" as input
3. for i=1 to r
4. xx=. ; *初始值在迴圈內, 未給初值, 沒有retain 時default 就為 . missing value;
5. if val[i] < 10 then XX=10; /* defalut xx=. missing value. */ /* 成立時 XX 為10, 不成立就為xx 為 missing value
6. end.
4. Do Until() , SET 多檔操作. (like Join at SQL)
有了前面的概念後, 就有機會來解釋以下的作法.
d1: 有欄位, id, name, price, ser
r: d1 資料筆數
ex1:
Data d2; *;
set d ; *假設 d有 r 筆資料(r>5);
if (_N_ >5) then delete; * keep 5筆, d2 為5筆;
Data bbb; *合併二檔;
set d (rename=(id=a_id name=a_name price=a_price ser=a_ser));
set d2;
run;
PSEUDO code:
create bbb, & open d, and d2;
for i=1 to r;
output id[i] name[i] price[i] ser a_id[i] a_name[i] a_price[i] a_ser[i]
end;
*新 bbb 共有r 筆, 合完後的檔 d2的變數, 只有前5筆有值, 最後補missing value, ;
Ex2: 此例子可以產生 leadpriceSum2= price+ lead1(price) 就是price+下一筆的_PRICE;
Data aaa;
set K1 (rename=(id=k1_id name=k1_name price=k1_price ser=k1_ser)); *改名字方便操作及辨識;
do until(exitf );
set K1 end=eof; ...
if (k1_ser+1=ser) then do;
exitf=1; *跳出後再從外圈回來會從 剛才處理的 K2的下一筆開始;
leadPriceSum2=price+k1_price;
end;
end;
keep k1_id k1_ser ser leadPriceSum2;
run;
*pseudo code
Data aaa;
open K1 as K1_b (rename=(id=b_id name=b_name price=b_price ser=b_ser)); *改名字方便操作及辨識;
open K1 as K2 end=eof;
do until(^ eof K1_b );
if (next eof K1_B) | (next eof K2 ) break; * 只要所開的檔其中有一個, 已經到最後一筆, 則下一個loop 就會結束;
do j=1 to R; *外圈: 給K1_B 用的;
do until (your_condition) | ( Next eof);
do i=cur to R; *內圈: 給第二個檔 K2 用的;
...
end;
cur=i;
if (your_condition) break; *跳出後再從外圈回來會從 剛才處理的 K2的下一筆開始;
end;
end; * end do j;
run;
[ref]: http://www2.sas.com/proceedings/forum2008/167-2008.pdf
...
SET MyDataset(FIRSTOBS=2 RENAME=(MyVariable=NextValue));
SET MyDataset;
StepValue = NextValue - MyVariable;
...;
我的相關文章
[Data Step][SAS] II. 如果要做 T, T-1 相關的計算要如何做 ?
