SAS中文论坛

标题: Stupid Human Tricks with PROC EXPAND® [打印本页]

作者: shiyiming    时间: 2010-11-4 21:21
标题: Stupid Human Tricks with PROC EXPAND®
From LCChien's blog on blogspot

Link:&nbsp;<a href="http://support.sas.com/resources/papers/proceedings10/093-2010.pdf"><!-- m --><a class="postlink" href="http://support.sas.com/resources/papers/proceedings10/093-2010.pdf">http://support.sas.com/resources/papers ... 3-2010.pdf</a><!-- m --></a><br /><br />鮮少有人知道 SAS/ETS 裡面有個叫做 PROC EXPAND 的程序。這個程序主要是用來整理時間序列資料,比方說可以自己定義時間區間後再來做一些次數量表的製作。David L. Cassell 利用這個程序進行了一些平常使用者可以用來做資料處理的功能,並發表了一篇教學文件在 SAS GLOBAL FORUM 2010 上。讓我們來看看如何用 PROC EXPAND 程序來取代一些複雜的資料操作。<br /><br /><a name='more'></a><br /><b>TRICK 1: LAGS AND LEADS</b><br />在 data step 裡面,我們可用 LAG() 或 LAGn() 函數來求出某個變數的前1~n天的數據,但如果反過來要找某變數的後1~n天數據,雖然有許多方法可以做,但並沒有一個簡便的 call function 可以處理。但是,用 PROC EXPAND 可以輕鬆地製作出這兩種數據出來。範例程式如下:<br /><code><span class="Apple-style-span" style="color: blue;">proc expand data=YourData method=none;<br />by pt;<br />convert dosedt = lead1_dt / transformout = (lead 1);<br />convert dosedt = lead2_dt / transformout = (lead 2);<br />convert dosedt = lag1_dt / transformout = (lag 1);<br />convert dosedt = lag2_dt / transformout = (lag 2);<br />run;</span></code><br />其中,我們打蘇案要轉換的變數是dosedt,而在 PROC EXPAND 裡面,只需要用 convert 指令,把新變數名稱定義好先(lead1_dt, lead2_dt, lag1_dt, lag2_dt),然後在後面斜線後加上一個 transformout= 的選項,然後在等號括弧裡面寫上 lead n 或 lag n 便可以造出後 n 天或指是前 n 天的變數。<br /><b>TRICK 2: MAX OR MIN OF THE LAST K RECORDS</b><br />如果想要知道某一個變數在前n筆或後n筆資料的最大值或最小值,一般的做法是會在PROC MEANS或PROC SUMMARY後加上一個where statement來限制程序要讀取的資料範圍,但在PROC EXPAND裡面,可以直接指定前n筆或後n筆資料,如下所示:<br /><code><span class="Apple-style-span" style="color: blue;">proc expand data=YourData out=YourMax method=none;<br />by factory;<br />convert x = max_x / transformin=(movmax 50);<br />convert x = min_x / transformin=(movmin 50);<br />run;</span></code><br />同樣利用convert statement,在後面加上transformin選項,並用"movmax n"或"movmin n"來讓SAS去讀前n筆或後n筆資料的最大值最小值。實際上SAS還是會從第一筆資料開始讀,每讀一筆資料就會算一次最大最小值,直到讀進來的資料數量大於movmax和movmin所指定的n值後,SAS才會開始去計算前n筆或後n筆資料的最大值最小值,而所有的結果都會完整呈現在新的資料裡面,我們只需要取最後一筆資料的x_max和x_min數據即為所求。<br /><span class="Apple-style-span" style="font-weight: bold;">TRICK 3: AGGREGATING CHUNKS OF RECORDS</span><br />我曾經在網路上看過很多人詢問過如何讓資料每跳幾筆資料算一個平均數,或者是每跳幾筆資料取一個數據。許多人用數個PROC程序和data step來完成這兩個動作,但在PROC EXPAND裡面,只需要兩個指令便可完成。<br /><br />假設資料如下:<br /><code><span class="Apple-style-span" style="color: blue;">data temp1;<br />input obs vol price;<br />datalines;<br />1 2 11<br />2 2 11<br />3 2 12<br />4 3 13<br />5 3 11<br />6 3 12<br />7 4 14<br />8 4 12<br />9 4 12<br />10 5 11<br />11 5 16<br />12 5 14<br />13 6 10<br />;<br />run;</span></code><br />總計十三筆資料,兩個變數(vol, price)。如果我們想要每三筆資料算一次vol的總值,以及每三筆資料抓出price的數據,則程式如下:<br /><code><span class="Apple-style-span" style="color: blue;">proc expand data=temp1 out=exp1 factor=(1:3);<br />convert vol=aggrvol / observed=total;<br />convert price=new_price / observed=end;<br />run;</span></code><br /><br />結果如下:<br /><code><span class="Apple-style-span" style="color: blue;">TIME AGGRVOL NEW_PRICE<br />0 6 12<br />3 9 12<br />6 12 12<br />9 15 14</span></code><br /><br />如何讓成是每三筆資料做一次運算,關鍵完全在PROC EXPAND後面的factor(n:m)選項。以此例來看,factor(1:3)便是要求SAS每三筆資料做一次運算。至於運算的方法,則是定義在convert statement後面的observed=選項。當observed=total時,則會求出每三筆資料的總合,當observed=end時,則會求出每三筆資料的最後一筆數據。實際上,observed=選項有許多參數可以設定,比方要算平均數就只要用observed=average即可。所有可使用的選項可以參考SAS線上手冊。<br /><br /><b>TRICK 4: THE MOVING AVERAGE</b><br />最後一個是算moving average,而這也是PROC EXPAND在處理時間序列資料時最常使用到的計算。假設我們要算每筆資料含前四筆資料的平均,程式如下:<br /><code><span class="Apple-style-span" style="color: blue;">proc expand data=temp1 out=YourOut method=none;<br />convert number1=mean1 / transformout=(movave 5);<br />run;</span></code><br />如同前面所述,我們只要在convert statement後面加上一個transformout=的選項,並於括弧內寫上"moveave 5"便可輕鬆算出moving average。<br /><br /><b>CONTACT INFORMATION</b><br />David L. Cassell<br />Design Pathways<br />3115 NW Norwood Pl.<br />Corvallis, OR 97330<br /><!-- e --><a href="mailto:DavidLCassell@msn.com">DavidLCassell@msn.com</a><!-- e --><br />541-754-1304<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6268919072942670865-2527293523266809738?l=sugiclub.blogspot.com' alt='' /></div>




欢迎光临 SAS中文论坛 (https://mysas.net/forum/) Powered by Discuz! X3.2