2017-02-23 125 views
1

我使用的是在http://www.sascommunity.org/mwiki/images/2/22/Hashmerge.sas發現%HASHMERGE宏和下面的示例數據集的:SAS哈希合併 - 小數據集作爲哈希對象

data working; 
    length IID TYPE $12; 
    input IID $ TYPE $; 
    datalines; 
    B 0 
    B 0 
    A 1 
    A 1 
    A 1 
    C 2 
    D 3 
    ; 
run; 

data master; 
    length IID FIRST_NAME MIDDLE_NAME LAST_NAME SUFFIX_NAME $12; 
    input IID $ FIRST_NAME $ MIDDLE_NAME $ LAST_NAME $ SUFFIX_NAME; 
    datalines; 
    X John James Smith Sr 
    Z Sarah Marie Jones . 
    Y Tim William Miller Jr 
    C Nancy Lynn Brown . 
    B Carol Elizabeth Collins  . 
    A Wayne Mark Rooney . 
    ; 
run; 

working數據集,我試圖附加_NAME變量從master數據集使用此散列合併。輸出看起來很好,是所需的輸出。但是,在我的真實場景中,master數據集太大,無法放入散列對象,並且該宏一直將其作爲散列對象。我最終想要將這兩個數據集翻到working數據集爲哈希對象的位置,但是當我翻轉代碼時,我無法獲得所需的輸出。下面是產生所需的輸出和需求調整了宏觀調控的一部分,但我不能確定如何設置此:

data OUTPUT; 
    if 0 then set MASTER (keep=IID FIRST_NAME MIDDLE_NAME LAST_NAME SUFFIX_NAME) 
    WORKING (keep=IID); 
    declare hash h_merge(dataset:"MASTER"); /* I want WORKING to be the hash object since it's smaller! */ 
    rc=h_merge.DefineKey("IID"); 
    rc=h_merge.DefineData("FIRST_NAME","MIDDLE_NAME","LAST_NAME","SUFFIX_NAME"); 
    rc=h_merge.DefineDone(); 
    do while(not eof); 
     set WORKING (keep=IID) end=eof; 
     call missing(FIRST_NAME,MIDDLE_NAME,LAST_NAME,SUFFIX_NAME); 
     rc=h_merge.find(); 
     output; 
     end; 
    drop rc; 
    stop; 
run; 

所需的輸出:

IID FIRST_NAME MIDDLE_NAME LAST_NAME SUFFIX_NAME 
--------------------------------------------------- 
B Carol  Elizabeth Collins  
B Carol  Elizabeth Collins  
A Wayne  Mark   Rooney 
A Wayne  Mark   Rooney 
A Wayne  Mark   Rooney 
C Nancy  Lynn   Brown 
D     
+0

您可以使用工作數據集的IID過濾主數據集,然後將過濾後的主數據集與工作數據集合並,因此這兩個數據集都很小,很容易處理。 –

+0

我嘗試了一個'SQL left join'過濾器,它花費的時間比讀取主數據集,排序和合並使用'if a'工作(in = a)master'花費的時間要長。 – Foxer

+0

試試這個過濾器:proc sql;創建表New_master作爲select * from master(keep = keep = IID FIRST_NAME MIDDLE_NAME LAST_NAME SUFFIX_NAME)where IID in(select IID from working(keep = IID));放棄; –

回答

0

雖然這是可行的,做你說,我懷疑你會從一個非專門製造的宏中獲得。那是因爲這不是通常的做法;通常你想保持主數據集的形式,並把關係數據集放在哈希表中。通常情況下,尺寸是相反的 - 關係表通常比主表小。

就我個人而言,我不會在這個特殊情況下使用散列。我會使用格式(或三)。就像散列一樣快,並且具有較小的尺寸問題(因爲它不需要適應內存),但由於尺寸的原因,它最終會放慢速度(但不會中斷!)。

格式的解決方案:

data working; 
    length IID TYPE $12; 
    input IID $ TYPE $; 
    datalines; 
    B 0 
    B 0 
    A 1 
    A 1 
    A 1 
    C 2 
    D 3 
    ; 
run; 

data master; 
    length IID FIRST_NAME MIDDLE_NAME LAST_NAME SUFFIX_NAME $12; 
    input IID $ FIRST_NAME $ MIDDLE_NAME $ LAST_NAME $ SUFFIX_NAME; 
    datalines; 
    X John James Smith Sr 
    Z Sarah Marie Jones . 
    Y Tim William Miller Jr 
    C Nancy Lynn Brown . 
    B Carol Elizabeth Collins  . 
    A Wayne Mark Rooney . 
    ; 
run; 

data for_fmt; 
    set master; 
    retain type 'char'; 
    length fmtname $32 
     label $255 
     start $255 
     ; 
    start=iid; 

    *first; 
    label=first_name; 
    fmtname='$FIRSTNAMEF'; 
    output; 

    *last; 
    label=last_name; 
    fmtname='$LASTNAMEF'; 
    output; 

    *middle; 
    label=middle_name; 
    fmtname='$MIDNAMEF'; 
    output; 

    *suffix; 
    label=suffix_name; 
    fmtname='$SUFFNAMEF'; 
    output; 

    if _n_=1 then do; 
    start=' '; 
    label=' '; 
    hlo='o'; 
    fmtname='$FIRSTNAMEF'; 
    output; 
    fmtname='$LASTNAMEF'; 
    output; 
    fmtname='$MIDNAMEF'; 
    output; 
    fmtname='$SUFFNAMEF'; 
    output; 
    end; 
run; 

proc sort data=for_fmt; 
    by fmtname start; 
run; 

proc format cntlin=for_fmt; 
quit; 

data want; 
    set working; 
    first_name = put(iid,$FIRSTNAMEF.); 
    last_name = put(iid,$LASTNAMEF.); 
    middle_name = put(iid,$MIDNAMEF.); 
    suffix_name = put(iid,$SUFFNAMEF.); 

run; 

也就是說......

如果你想做到這一點在哈希表中,你需要做的是,對每一行MASTER什麼,在工作表中做一個FIND,然後如果成功了一個REPLACE,那麼FIND_NEXT和REPLACE直到失敗。

問題?你至少在每個主排處找到至少一個找到,你自己指出這是非常大的。如果WORKING爲100k,MASTER爲100M,那麼您爲每場比賽做了1000次查找。這非常昂貴,並且可能意味着您最好使用其他解決方案。

+0

感謝一如既往的卓越建議,@Joe。有道理,因爲我的場景使用散列表沒有太多的文檔。我會給格式方法一個鏡頭! 'WORKING'有22MM的行,'MASTER'有一些類似350MM的行 - 討厭的東西,但必須完成。 – Foxer

+0

我絕對不會用散列做 - 然後找到另一個解決方案。也許把MASTER分成幾組並散列。你可以在散列中填入多大的大小?你有多少內存?獲得更多的內存或更小的數據集 - 例如,如果您可以在散列中容納100MM,則四個散列可能就足夠了,特別是如果您能夠智能地分割它(例如索引),那麼您只能從WORKING加載5MM行,從MASTER校正100MM行,而不是每次22/100)。 – Joe