登录
首页精彩阅读SAS—HASH对象的应用
SAS—HASH对象的应用
2017-06-04
收藏

SAS—HASH对象的应用

HASH table原理

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

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

比如我最爱的杰伦,根据散列函数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;

数据分析咨询请扫描二维码

客服在线
立即咨询