SAS哈希合并 - 小数据集作为哈希对象

问题描述:

我使用的是在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));放弃; –

虽然这是可行的,做你说,我怀疑你会从一个非专门制造的宏中获得。那是因为这不是通常的做法;通常你想保持主数据集的形式,并把关系数据集放在哈希表中。通常情况下,尺寸是相反的 - 关系表通常比主表小。

就我个人而言,我不会在这个特殊情况下使用散列。我会使用格式(或三)。就像散列一样快,并且具有较小的尺寸问题(因为它不需要适应内存),但由于尺寸的原因,它最终会放慢速度(但不会中断!)。

格式的解决方案:

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