2017-05-19 17 views
0

我遇到問題。當ID隨時間變化時,我需要爲另一張桌子創建人行橫道。無論ID有什麼變化,我都需要有第一年的ID。SAS:根據隨時間變化的值進行人行橫道

data have; 
input ORIG_ID $ CHANGE_ID $ YEAR 
AAA BBB 1990 
BBB AAA 1991 
PPP ZZZ 1993 
ZZZ YYY 1994 
YYY ZZZ 1996 
TTT MMM 1990 
; 

**What I want :** 

/****OUTPUT****/ 

CHANGE_ID ORIG_ID 
BBB  AAA 
ZZZ  PPP 
YYY  PPP 
MMM  TTT 
/*My logic so far*/ 
proc sql; 
    create table temp as 
    select CHANGE_ID, ORIG_ID 
    case 
     when (CHANGE_ID<ORIG_ID) then cat(CHANGE_ID,ORIG_ID) 
     when (ORIG_ID<CHANGE_ID) then cat(ORIG_ID,CHANGE_ID) 
     end as key, year 
    from dat 
    order by key,year; 
quit; 

data final; 
    retain CHANGE_ID ORIG_ID 
    set temp; 
    by key; 
    if first.key; 
run; 
/*But this works for id changing for AAA to BBB, may be not*/ 

讓我知道如果您有任何困惑:

+0

我從來沒有聽說過數據科學或統計方面的人行橫道。您是否在談論審計跟蹤以跟蹤ID值如何改變? –

+0

呵呵:)。這個人行橫道是另一個數據集所需要的,這個數據集隨着時間的推移而發生id變化,有時id會變回原來的值,最壞的情況下id會不斷變化。我們希望將所有更改的ID保留爲第一次出現的位置。你能理解這個嗎? – ammosperros

回答

1

這裏是一個哈希對象的方法 - 它應該工作提供了

  • 你有足夠的內存來容納整個輸入表
  • 每年每個ID只有1個更改
  • 如果每年每個ID有多個更改,可以採用某種方式對更改進行排序


data have; 
input ORIG_ID $ CHANGE_ID $ YEAR; 
cards; 
AAA BBB 1990 
BBB AAA 1991 
PPP ZZZ 1993 
ZZZ YYY 1994 
YYY ZZZ 1996 
TTT MMM 1990 
; 
run; 

proc sort data = have; 
by CHANGE_ID descending YEAR; 
run; 

data v_have /view = v_have; 
    set have; 
    by CHANGE_ID; 
    if first.CHANGE_ID then GRP = 0; 
    GRP + 1;  
run; 


data want; 
    informat CHANGE_ID ORIG_ID; 
    set v_have; 
    /*Although we need the whole table in the hash, we only need to process each CHANGE_ID once*/ 
    by CHANGE_ID; 
    if first.CHANGE_ID; 

    /*Create a hash object to hold the table*/ 
    if _n_ = 1 then do; 
    dcl hash h(dataset:'v_have'); 
    rc = h.definekey('CHANGE_ID','GRP'); 
    rc = h.definedata('ORIG_ID','YEAR'); 
    rc = h.definedone(); 
    end; 

    /*Make a temp copy of the starting ID*/ 
    T_CHANGE_ID = CHANGE_ID; 
    PREV_YEAR = 2000; 
    rc=0; 

    /*Follow chains of IDs backwards through the table, making sure we only step backwards in time to avoid looping*/ 
    do while(rc = 0 and YEAR < PREV_YEAR); 
    PREV_YEAR = YEAR; 
    CHANGE_ID = ORIG_ID; 
    /*If there are multiple records per CHANGE_ID, take the most recent one that's younger than the current record*/ 
    do GRP = 1 by 1 while(rc=0 and YEAR >= PREV_YEAR); 
     rc = h.find(); 
    end; 
    end; 

    /*Output the last CHANGE_ID we got to plus the starting ID */ 
    ORIG_ID = CHANGE_ID; 
    CHANGE_ID = T_CHANGE_ID; 

    /*Ignore trivial rows resulting from cycles*/ 
    if CHANGE_ID ne ORIG_ID; 
    keep CHANGE_ID ORIG_ID; 
run; 

現在稍微複雜一些,但正常工作。我可能會用一個多數據散列對象來做這件事,因爲我認爲這樣可以消除初始排序。

+0

謝謝我們接近,但上面沒有給我們期望的輸出。讓我們請記住,原始編號應該始終是第一年發生的編號。對於我來說,輸入是字母數字,而年份就像201201 201203 up-to 999912. – ammosperros

+0

我已經改變了算法,以便它現在可以使用通用日期並生成所需的輸出。 – user667489

+0

謝謝。算上我是你的粉絲吧。我仍然需要一些時間來弄清楚算法是如何實現這一功能的。 – ammosperros