2013-02-08 90 views
0

原始數據集是這樣的:創建新變量條件的其他[SAS]

sub month y 
1 1  1 
1 2  2 
1 3  3 
1 5  5 

我想要的是讓基於一個月前3個YS爲每個主題,如果y在當月失蹤,那麼新變量也是.。比方說,對於上面的例子,LAG1是上個月以前ylag2是前一個y 2個月前,lag3是迄今爲止等等:

sub month y lag1 lag2 lag3 
1 1  1 . . . 
1 2  2 1 . . 
1 3  3 2 1 . 
1 5  5 . 3 2 

的事情是我簽出lagdif功能,但在我的情況下,我想在lag取決於month和月之間也有差距,所以我不能使用像lag1函數的前一個。

此外,我也需要爲許多主題做到這一點。謝謝。

+0

「滯後取決於時間」是什麼意思?我沒有看到名爲「time」的變量。另外,給定原始數據集,第二個數據塊是否正是您想要的結果? – BellevueBob 2013-02-08 21:43:09

+0

@BobDuell我很抱歉混淆。我只是將變量'time'改爲'month',以使我的問題更清晰。是的,第二個是我想要的。 – liuminzhao 2013-02-08 21:44:36

+0

我很抱歉,但我不明白你想要做什麼。對於第四個obs,「lag2」等於「3」以什麼方式?是否因爲月份存在差距(就好像有一行「月份= 4」)? – BellevueBob 2013-02-08 22:11:33

回答

2

SQL解決方案:

data have; 
input sub month y; 
datalines; 
1 1  1 
1 2  2 
1 3  3 
1 5  5 
;;;; 
run; 

proc sql; 
create table want as 
    select H.sub,H.month, H.y, One.y as lag1, Two.y as lag2, Three.y as lag3 
    from have H 
    left join (select * from have) One on H.sub=One.sub and H.month=One.month+1 
    left join (select * from have) Two on H.sub=two.sub and H.month=Two.month+2 
    left join (select * from have) Three on H.sub=three.sub and H.month=Three.month+3 
; 
quit; 

顯然,如果你想讓他們的36本變得有點長,但它至少也沒有那麼複雜。有各種其他方式來做到這一點。不要使用LAG,這將是一個令人頭疼的問題,反正也不合適。如果您熟悉哈希的概念,哈希表可能更有效,並且需要更少的編碼。

哈希的解決方案:

data want; 
if _n_ = 1 then do; 
declare hash h(dataset:'have(rename=y=ly)'); 
h.defineKey('sub','month'); 
h.defineData('ly'); 
h.defineDone(); 
call missing(sub,month,ly); 
end; 
set have; 
array lags lag1-lag3; 
do prevmonth = month-1 to month-3 by -1; 
    if prevmonth le 0 then leave; 
    rc=h.find(key:sub,key:prevmonth); 
    if rc=0 then lags[month-prevmonth] = ly; 
    call missing(ly); 
end; 
run; 

這是很簡單的向上擴展到36或什麼 - 只是改變了數組的長度array lags lag1-lag36和做聲明do prevmonth=month-1 to month-36 by -1;最多的工作,你可能需要做是安排的東西,所以月份在這裏工作 - 無論是通過創建一個整數月份,或更改循環標準與月/年或什麼不工作。你不顯示你的數據是如何指定的,所以不能幫助你。

+0

不錯。在你的SQL建議中沒有看到派生表的原因;一個簡單的連接似乎就足夠了 – BellevueBob 2013-02-08 22:21:38

+0

這很容易理解。謝謝,這是有效的。 – liuminzhao 2013-02-08 22:41:46