我使用http://www.sascommunity.org/mwiki/images/2/22/Hashmerge.sas处的%HASHMERGE
宏和以下示例数据集:
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 :(得分: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次查找。这非常昂贵,可能意味着你可以通过其他解决方案获得更好的效果。