SAS—HASH对象的应用

转自公众号:数据分析sas和r和python


回复「朝阳35处」可查看「说人话的大数据」系列合辑


SAS—HASH对象的应用



前言
▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼

春节归来,今天才终于恢复到正常工作的心态,对于我这个迟到狂魔好不容易早去上班,结果迷糊地下错地铁站,还走到了出口,最终还是迟到1分钟真的是上班不容易呀/(ㄒoㄒ)/~~。

不过春天要来了,万物复苏的季节,想着怎么也要总结一下去年的工作,下周开始记录下用R语言开发信用卡评分建模程序吧。

废话不多说了,今天主要给大家介绍下sas的hash对象的应用。因为篇幅有限,本篇文章只做大概介绍,如有兴趣,请加我好友,我会发资料给大家。

▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
HASH table原理

先介绍下hash的原理吧。hash table其实就是散列表,也叫哈希表根据关Key-value键值对而直接进行访问的数据结构。它通过把key-value映射到表中一个位置来访问记录,不用扫描整张表以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做哈希表。

在数据装载时,根据F(key)=内存地址将表存到内存中指定的地址。

 key value内存地址(举例)
周杰伦
 87A1=F(周杰伦)=18
小红 98A2=F(小红)=20
小明 69A3= F(小明)=36
小二 83A4= F(小二)=48

 比如我最爱的杰伦,根据散列函数F(周杰伦) = 18 就可找到对应的value为87啦。


sas hash table 的优点

hash table是 SAS 查找技术中最为常用的技术啦,性能表现经评测也比较上乘,在SAS 产品中已被广泛使用,同时也深受国外SAS程序员的喜爱,但在国内大家好像并不怎么常用。但是想想可以用sas hash提高下数据查询的效率,是不是在小伙伴面前有些小逼格呢!?

下面呢就介绍下sas hash table的优点:

1.hash table 可以根据 K-V 定位数据,直接得到变量的存储地址,可以减少查询的次数;

2.hash table的变量查找是在内存中进行的,可以提高性能;

3.hash table可以在data步运行时的动态地添加、更新、删除等操作;

4.hash 可以做一些merge 和 proc sql 难以实现的数据集合并,并在细节上可以有更多的控制。

当然,因为sas hash是在内存中运行,所以如果数据太大,还是不要用hash对象了。

sas 定义hash对象

Hash对象的最基本的要点有三个:

(1)要放入内存中的表

 (2)用来通过hash函数建立与内存对应存储地址的KEY值(可以是数值、字符或者两者的混合,最好是表的主键否则只有第一条记录有效,因为key值相同通过F(key)只会指向一个地址)。

(3)要调入内存中与key值一起构成数组的变量.

在SAS中分别通过以下步骤来完成上述三个要点

hash的使用实例

(1)通过hash可以实现表与表的高效关联

(2)可以对hash表中的数据进行控制设计巧妙的算法。下边是一些具体的例子:

  1. 使用hash对象来筛选数据

/*新入职员工信息*/

data id_newly;

input id $  epl_ym;

cards

;

1101 201201

1102 201201

1123 201203

1105 201202

1104 201202

1105 201202

;

run;

如下图所示:

/*创建每位员工的销售级别及销售额*/

data sales_all;

input id $ grade $ amt;

cards

;

1001 a 561

1101 c 256

1002 b 421

1003 a 691

1005 a 555

1004 b 398

1015 a 402

1102 c 128

1123 d 96

1105 c 196

1104 d 89

1086 b 632

1093 a 701

1115 c 221

;

run;

如下图所示:

/*使用hash对象筛选新员工的销售额*/

data sales_newly;

length id $8. epl_ym 8.;/*定义数据变量id、epl_ym类型和长度,此处将变量类型和长度写死在程序里,这样当查找表的数据结构发生变化时还要重写代码。以后会单独介绍一下hash 对象处理的技巧。

*/

if _n_ = 1 then do;

declare hash newly(dataset:'id_newly');/*使用数据集id_newly定义hash对象*/

newly.definekey('id');/*其中定义id为主键*/

newly.definedata('epl_ym');/*定义epl_ym为信息变量*/

newly.definedone();/*结束hash对象的初始化*/

end;

set sales_all;

rc = newly.find(key:id);/*调用find方法检索数据集sales_all中的变量id的值是否出现在hash对象的主键中*/

if rc = 0;/*此处注意,find()找到匹配的值返回的是0,这个和其他语言不同。*/

run;

所得结果如下:

 2.使用hash对象拼接数据

/*创建销售等级对应的佣金比例数据集*/

data grade;

input grade $ rate;

cards

;

a 0.20

b 0.18

c 0.15

d 0.10

e 0.05

;

run;

结果如下:

/*计算佣金*/

data csm_amt;

if _n_ = 0 then do;

set id_newly grade;

end;

else if _n_ = 1 then do;

declare hash newly(dataset:'id_newly');

newly.definekey('id');

newly.definedata('epl_ym');

newly.definedone();

declare hash grd(dataset:'grade');

grd.definekey('grade');

grd.definedata('rate');

grd.definedone();

end;

call missing (of _all_);

set sales_all;

rc1 = newly.find(key:id);

rc2 = grd.find(key:grade);

if rc1 = 0 then csm_amt = amt*rate;

run;

 3.调用definedata 时使用all选项

/*小组信息*/

data team_info;

input team $ open_ym grade employees;

cards

;

a 201201 12 6

b 201202 11 9

c 201205 9 12

d 201506 7 20

e 201205 8 9 

f 201206 10 23

;

run;

所得数据集如下:

data employ_new;

input id $ team $;

cards

;

2001 c

2036 d

;

run;

data newly_info;

if _n_ = 0 then do;

set team_info;

end;

else if _n_ = 1 then do;

declare hash t(dataset:'team_info');

t.definekey('team');

t.definedata(all:'yes');

t.definedone();

end;

call missing(of _all_ );

set employ_new;src = t.find();

run;



最后欢迎大家加我微信,共同学习。





1月原创好文回顾,请点击阅读:

朝阳35处|数据科学的江湖:剑宗与气宗之争

零道书院|“羊毛党”最怕啥?

朝阳35处|为了拜年,处座竟曝了这么多料

7扇门|强拳出击,让老赖无所遁形!

朝阳35处|新不孝有三:单身、坑爹和____

零道书院|隐写术:FBI需要你的协助

前海征信七扇门|6个风控的血泪教训

零道书院 | 区块链梦想之“天下无贼”

朝阳35处|大数据揭秘:跟你一样抢不到票的都有谁?

7扇门|人脸识别技术有漏洞?快来看看如何升级