【转载】SAS Hash 对象
来源:互联网 发布:大庆油田网络客服电话 编辑:程序博客网 时间:2024/05/17 09:22
1.基本原理
散列表(Hash table,也叫哈希表),是根据关键码值(Keyvalue)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
在数据装载时,根据F(key)=内存地址将表存到内存中指定的地址;
2.SAS中定义的HASH对象:
Hash对象的最基本的要点有三个:
(1)要放入内存中的表
(2)用来通过hash函数建立与内存对应存储地址的KEY值(可以是数值、字符或者两者的混合,最好是表的主键否则只有第一条记录有效,因为key值相同通过F(key)只会指向一个地址)。
(3)要调入内存中与key值一起构成数组的变量.
3.在SAS中分别通过以下步骤来完成上述三个要点:
(1)发布HASH对象
DECLARE hash hash_name(<</SPAN>dataset: 'dataset_name',ordered:'');
Object:指定对象,只能是hash或hiter;
hash_name:为建立的hash对象命名,便于后边调用。
dataset: 'dataset_name',指定要放入内存中的数据集
ordered: 'option' 装入内存中的数据要不按key进行排序,'option''是下面几种:ascending' | 'a';'descending' | 'd';'YES' | 'Y'; 'NO' | 'N'默认: NO 。
例如:
declare hash h (dataset:'work.a',ordered:'ascending');
按关键字的升序将数据集读入内存通过hash函数建立hash表。
(2)指定key值变量 hash_name.difinekey(“key_1”…);
例如:h.definekey('var1','var2');
(3)指定要加载哪些数据变量 object.difinedata(“variable_1”…);
例如:h.definedata('var1','var2','var3') 加载指定的变量;
or h.definedata(all:'yes') 把表中的所有变量都加载进来;
(4)执行object.definedone()说明hash表已经在内存中准备好了,可以随时调用了。
Call missing(key,variable_1)避免log里出现数据未初始化的提醒。
3.SAS中使用已经定义好的Hash表的方法有以下7种:
1)ADD方法:增加指定的数据到hash中,数据中必须包括已经存在的hash的key值
2)CHECK 方法:检查具体的key的取值是否已经存储在hash中
4)DELETE 方法:删除已经定义的hash
5)OUTPUT 方法:创造一个或多个数据集(数据包含在hash中)
6)REMOVE方法:移除hash中key的某个特定值(针对观测值/行)
7)REPLACE方法:替换hash中key的某个特定值后边所带的变量值(针对观测值/行)
8)Hash Iterator 方法
9) h.num_items 返回唯一的key值数
4.hash的使用实例
(1)通过hash可以实现表与表的高效关联
(2)可以对hash表中的数据进行控制设计巧妙的算法。下边是在网上搜集的一些具体的例子:
eg1.通过hash对数据集进行排序,并输出排序后的数据集
data test;eg2.把哈希表中指定的观测输出或者做处理
data work.test;
input keyvalue ;
datalines;
1 2
1 3
2 4
2 5
3 6
3 7
;
run;
data test_2;
if _n_=0 then set test;
if _N_ = 1 then do;
declare hash h(dataset: 'work.test');
('h'); declare hiter iter
h .defineKey('key','value');
h .defineData(all:'yes');
h .defineDone();
end;
rc = iter.first();
do while(rc=0);
if key=2 then output;
=iter.next(); rc
end;
drop rc;
run;
eg3.主表调用hash表的数据(这个例子是从网上转载的,hash应用较为的经典案例,值得反复揣摩品味)
要求:A表是每日基金净值表,其中name是基金名称;date是收盘日期;value是当日净值。B表是各客户持有各基金的起始日期与终止日期,其中name是基金名称,sdate是起始日期,edate是终止日期。真实环境中:A表不大,只有几千条记录;B表巨大,会有一亿条记录。
目标表C含有各客户持有各基金起始日期的净值;终止日期的净值;期间净值累计值。即在保留B表所有字段的基础上衍生计算三个字段:svalue(起始日期的净值);evalue(终止日期的净值);tvalue(期间净值累计值)。 data value;
input name $ date value;
informat date yymmdd8.;
format date date9.;
cards;
A 20070101 1
A 20070102 2
A 20070103 3
A 20070104 4
A 20070105 5
A 20070106 6
A 20070107 7
B 20070101 8
B 20070102 9
;
run;
data original;
input name$ sdate edate;
informat sdate edate yymmdd10. ;
formatsdate edate yymmdd10 . ;
datalines;
A 20070102 20070106
A 20070101 20070104
B 20070101 20070102
;
run;
data cum_value;
if _n_=0 then set value;
if _n_=1 then do;
declare hash h(dataset:'value');
h.definekey('name','date');
h.definedata(all:'yes');
h.definedone();
end;
set original;
rc =h.find(key:name,key:sdate);
s_value =value;
rc =h.find(key:name,key:edate);
end_value =value;
sum_value =0;
do i=sdate to edate;
rc =h.find(key:name,key:i);
sum_value +value;
end;
keep name sdate edate s_value end_value sum_value;
run;
eg4.调用hash表自身数据进行计算
A客户有三条记录,每条记录的金额均小于200,;B客户有5条记录,每条记录的金额均大于150,但小于400。
条件:如果某个客户的总金额(该客户所有记录的金额加和)<</SPAN>600,则将该客户的所有记录删除。如上例中,A客户总金额<</SPAN>600,则删除A客户。
data test;
input id $ amount;
datalines;
A189
B160
B188
B165
A145
A199
B198
B345
;
data wanted;
if 0 then set test;
if _n_=1 then do;
declare hash h();
h.definekey('id');
h.definedata('id','total');
h.definedone();
end;
do until(last);
set test end=last;
if h.find()=0 then do;
total+amount;
h.replace();
end;
else do;
total=amount;
h.add();
end;
end;
do until(last1);
set test end=last1;
if h.find()=0 and total>=600 then output;
end;
stop;
run;
最后一个例子:
data salaries;
input empnum salary;
format salary dollar10.;
datalines;
1234 125000
3333 85000
4876 54000
5489 29000
;;;;
proc print data=salaries;
title "SALARIES";
run;
data brackets;
input empnum tax_bracket;
datalines;
1111 0.28
1234 0.33
3333 0.28
4222 0.15
4876 0.25
;;;;
proc print data=brackets;
title "BRACKETS";
run;
data netpay;
attrib empnum length=8
salary length=8 format=dollar10.
tax_bracket length=8 format=4.2
net_pay length=8 format=dollar10.;
retain default_bracket .10;
drop default_bracket rc;
if _n_=1 then do;
declare hash b(dataset:'brackets');
b.defineKey('empnum');
b.defineData('tax_bracket');
b.defineDone();
end;
set salaries;
rc=b.find();
if rc ne 0 or tax_bracket=. then tax_bracket=default_bracket;
net_pay=salary*(1-tax_bracket);
run;
proc print data=netpay;
title "Example 4.1 Related Technique 1 NETPAY Data Set Created with DATA Step";
run;
- 【转载】SAS Hash 对象
- 【转载】SAS INTNX详解
- 一致性 hash 算法(转载)
- SAS hash 树与多维临时数组的比较
- em的错误 <转载>
- ORADEBUG DOC <转载>
- SAS--Perl Regular Expressi…
- How to pass a hash to a subrouti…
-  
- linux top (转载)
-
- Why ASMLIB and why not? <转载…
- javascript 浅析 对象 function
- HTML DOM Table 对象
- JavaScript HTML DOM 对象
- 同步 异步 阻塞 非阻塞 (转载)
- javascript 对象 属性
- IOS --- 对象归档
- sql合并复杂的表
- 【转载】正则表达式基础知识介绍及…
- SAS--Perl Regular Expressi…
- php面向对象编程之构造方法 __construct()
- 【转载】word 查找与替换中的…
- 【转载】SAS Hash 对象
- C#单链表的实现
- 双set表整合出复杂的表(附有sas&n…
- VLAN原理详解
- SAS hash 树与多维临时数组的比较
- 【转载】python基础一(加了我的注…
- android:descendantfocusability
- 【转载】Python 基础语法(二)…
- logistic 回归