SAS中的多个哈希对象
我有两个SAS数据集。第一个相对较小,包含唯一的日期和相应的ID:SAS中的多个哈希对象,sas,Sas,我有两个SAS数据集。第一个相对较小,包含唯一的日期和相应的ID: date dateID 1jan90 10 2jan90 15 3jan90 20 ... 第二个数据集非常大,有两个日期变量: dt1 dt2 1jan90 2jan90 3jan90 1jan90 ... 我需要将dt1和dt2与dateID匹配,因此输出为: id1 id2 10 15 20 10 效率在这里非常重要。我知道如何使用散列对象进行一次匹配,因此我可以对d
date dateID
1jan90 10
2jan90 15
3jan90 20
...
第二个数据集非常大,有两个日期变量:
dt1 dt2
1jan90 2jan90
3jan90 1jan90
...
我需要将dt1
和dt2
与dateID
匹配,因此输出为:
id1 id2
10 15
20 10
效率在这里非常重要。我知道如何使用散列对象进行一次匹配,因此我可以对dt1
执行一个数据步骤,然后对dt2
执行另一个步骤,但我希望在一个数据步骤中同时执行这两个步骤。如何做到这一点
下面是我将如何仅对dt1
进行匹配:
data tbl3;
if 0 then set tbl1 tbl2;
if _n_=1 then do;
declare hash dts(dataset:'work.tbl2');
dts.DefineKey('date');
dts.DefineData('dateid');
dts.DefineDone();
end;
set tbl1;
if dts.find(key:date)=0 then output;
run;
目前我面前没有SAS来测试它,但代码如下所示:
data tbl3;
if 0 then set tbl1 tbl2;
if _n_=1 then do;
declare hash dts(dataset:'work.tbl2');
dts.DefineKey('date');
dts.DefineData('dateid');
dts.DefineDone();
end;
set tbl1;
date = dt1;
if dts.find()=0 then do;
id1 = dateId;
end;
date = dt2;
if dts.find()=0 then do;
id2 = dateId;
end;
if dt1 or dt2 then do output; * KEEP ONLY RECORDS THAT MATCHED AT LEAST ONE;
drop date dateId;
run;
给定哈希表的大小,格式可能同样有效
data fmt ;
retain fmtname 'DTID' type 'N' ;
set tbl1 ;
start = date ;
label = dateid ;
run ;
proc format cntlin=fmt ; run ;
data tbl3 ;
set tbl2 ;
id1 = put(dt1,DTID.) ;
id2 = put(dt2,DTID.) ;
run ;
根据以下评论编辑的版本
data fmt ;
retain fmtname 'DTID' type 'I' ;
set tbl1 end=eof ;
start = date ;
label = dateid ;
output ;
if eof then do ;
hlo = 'O' ;
label = . ;
output ;
end ;
run ;
proc format cntlin=fmt ; run ;
data tbl3 ;
set tbl2 ;
id1 = input(dt1,DTID.) ;
id2 = input(dt2,DTID.) ;
run ;
首先,我同意格式解决方案,但是如果你想做散列解决方案,就这样吧。这里最基本的一点是,将键定义为要匹配的变量,而不是散列本身
data tbl2;
informat date DATE7.;
input date dateID;
datalines;
01jan90 10
02jan90 15
03jan90 20
;;;;
run;
data tbl1;
informat dt1 dt2 DATE7.;
input dt1 dt2;
datalines;
01jan90 02jan90
03jan90 01jan90
;;;;
run;
data tbl3;
if 0 then set tbl1 tbl2;
if _n_=1 then do;
declare hash dts(dataset:'work.tbl2');
dts.DefineKey('date');
dts.DefineData('dateid');
dts.DefineDone();
end;
set tbl1;
rc1 = dts.find(key:dt1);
if rc1=0 then id1=dateID;
rc2 = dts.find(key:dt2);
if rc2=0 then id2=dateID;
if rc1=0 and rc2=0 then output;
run;
很好的解决方案。关于这种方法的查找表可以有多大,有什么指导吗?假设
tbl1
有10000条记录。。。您还会推荐这种方法吗?格式和哈希在查找数千个数据集时非常相似。我不认为你开始遇到格式问题,直到几十万。不过,这两种方法的工作原理非常相似,因此在10000条记录时,您可能不会看到太多差异(当然,您应该始终针对您的特定需求进行测试)。如果要进行非匹配,请不要忘记在fmt数据集中包含hlo='o'记录-这是针对非匹配的。否则,您将获得原始值,这可能不容易验证。在格式数据集中运行了10000个测试,在更大的数据集中运行了100万个测试,结果非常相似。格式化花了.57秒,散列花了.45秒,所以散列可能稍微快一点,但差别不大(这么小可能是处理器负载的随机变化)。太好了,非常感谢。愚蠢的问题:如前所述,这会导致id
变量具有字符值,但我需要数字。我应该转换它们,还是有不同的格式?Thank.INPUT代替PUT,创建一个informat代替格式。Type='N'是一种格式,Type='I'(I)是一种信息。