鉴于很多论坛成员已经购买了我的《SAS编程与数据挖掘商业案例》一书,有些读者对书中提到的Hash技术很感兴趣,在该书中,只有大约3个商业实践的案例。最近我刚好完成了一个涉及到文本聚类的项目,其中用到了Hash,在此以飨读者,更多的文本聚类的代码我会在《SAS编程与数据挖掘商业案例》一书第二版提供给读者。
需求:假设有两个关键字'c b b a'和'w w a'(已经经过数据清洗),显然,该关键字有四个distinct的token,它们是:w;a;b;c。要求生成如下的向量空间模型:
kw w c b a
c b b a 0 1 2 1
w w a 2 0 0 1
.
显然,有很多种方法可以实现,我在此提供一种通过Hash技术来实现的方法:
data test;
kw='c b b a';
output;
kw='w w a';
output;
run;
data hash;
input token_list $ @@;
cards;
w c b a
;
run;
data output;
If 0 Then Set hash;
If _N_=1 Then Do;
Declare Hash Share(Dataset:"hash",ordered: 'yes');
declare hiter iter("Share");
Share.Definekey ('token_list');
Share.Definedata('token_list');
Share.Definedone();
End;
set test;
length ar1-ar4 3;
array ar[1:4] ;
length first_token_main1 last_token_main1
first_token_hash1 last_token_hash1 main_word1 hash_word1 $10;
first_token_main1=upcase(compress(scan(kw,1,' ')));
last_token_main1=upcase(compress(scan(kw,count(trim(kw)," ")+1,' ')));
rc=iter.first();
iter_cnt=0;
DO WHILE (rc=0);
match_count=0;
first_token_hash1=upcase(compress(scan(token_list,1,' ')));
last_token_hash1=upcase(compress(scan(token_list,count(trim(token_list)," ")+1,' ')));
IF (last_token_main1 gt first_token_hash1 or last_token_hash1 gt first_token_main1) THEN DO;
iter_cnt+1; ar(iter_cnt)=0;go to next;
END;
m=1;
Do While (compress(scan(kw,m,' ')) ne '');
main_word1=upcase(compress(scan(kw,m,' ')));
n=1;
do while (compress(scan(token_list,n,' ')) ne '');
hash_word1=upcase(compress(scan(token_list,n,' ')));
if (main_word1 gt first_token_hash1) then do;leave;end;
if (main_word1 gt hash_word1) then do;leave;end;
if (main_word1 eq hash_word1) then do;match_count+1;leave;end;
n+1;
end;
m+1;
End;
iter_cnt+1;
ar(iter_cnt)=match_count;
next:rc = iter.next();
END;
keep kw ar1-ar4;
run;
注意:对上面这段代码需要读者有一定的SAS基础,并已经对我《SAS编程与数据挖掘商业案例》书中提到的Hash的基础知识有了一定了解后,看起来会更有效。