sas hash基础

时间:2024-10-30 07:01:53


    在SAS中我们比较习惯使用DATA步来解决数据处理工作,但是当我们需要处理的是两个以上有关联的数据文件或需要处理的数据观测记录达到百万级别时,DATA步显然不能满足我们的要求。若使用hash散列表(哈希表),把关键字映射到散列表中,通过散列表直接获取需要访问数据的存储地址,可以快速的进行查找、添加等操作。
    SAS提供了hash和hiter两种方法处理哈希表,hash提供了查找、修改、添加、删除等方法,hiter提供了用于定位和遍历等方法。
1.1 Hash的定义及使用
在使用之前需要定义哈希表,如下:
Daclare hash myhash;
myhash=_new_  hash(); 
或者:Declare hash myhash();
例如:
Daclare hash my_hash;my_hash =_new_  hash();定义了一个名字为my_hash的哈希表。
初始化哈希表:
declare hash variable_name(argument_tag-1 : value-1<, ...argument_tag-n: value-n>);
或者:
variable_name = _new_  hash(argument_tag-1: value-1<, ...argument_tag-n: value-n>);
例如:declare hash h(hashexp:4,dataset: '', ordered: 'yes');定义了一个名字为h的哈希表,并且把的数据映射到哈希表上;hashexp:4表示哈希表的大小定为2的4次方,ordered: 'yes'表示在哈希表中根据关键字升序排序。
语句解读:
使用第一种方法定义哈希表时需要注意myhash是定义的表名,其余部分为固定格式。
初始化时可选填的项有:
Hashexp:n  指定哈希表的大小为 ,但并不表示观测数。默认为8。

Dataset:`dataset_name' 指定需要映射到哈希表的数据集。
Ordered:’option’ 指定输出到数据集或读取数据时是否排序,option选项如下:
 Ascending和yes表示根据key升序;Descending表示根据key值降序;no为不做任何操作。此外各选项均可只用首字母代替。
duplicate: ’option’ option选项如下:replace表示遇到相同key时,仅保留最后一条观测;error表示遇到相同的key时,在日志窗口报错
multidata: ’option’ ’option’选项如下:yes表示允许重复的key在哈希表中出现,no则不允许,默认情况为不允许。

在定义一个新的哈希表后需要指定哈希表的关键字段等,如下:
语句 功能
DEFINEKEY 定义关键字段;
DEFINEDATA 定义值;
DEFINEDONE 定义完成;
CALL MISSING 避免提示变量未初始化

哈希表中可以实现较多的操作,语句格式如下:
myhash.’option’();
option可选选项句及功能:
语句 功能
FIND 查找相同的键值,存在则返回rc=0;
ADD 添加键值,若hash表中已存在,则不添加;
CHECK 查找健值,若存在返回rc=0;
REPLACE 若哈希表中不存在指定的关健字段,则添加;若存在则替换;
REMOVE 移去哈希表中指定关键字对应的地址等数据;
EQUAL 判断两个哈希表是否完全相等;
OUTPUT 将哈希表输出到数据集;
REF 若查找关键字成功则无操作,若查找不成功则添加关键字,相当于find与add的结合;
SETCUR 规定一个关键字,用于起始迭代。通常在对数据排序后使用。
SUM 计算并返回相同key下指定计数变量的和
CLEAR 清空hash表,但不删除数据;
DELETE 删除整个哈希表
NUM_ITEMS 计算哈希表中观测的条数
ITEM_SIZE 计算哈希表的大小

在哈希表中还有如下操作,与上述操作不同的是,使用下列的操作必须在允许哈希表中出现相同的关键字前提下。
HAS_NEXT 在允许出现相同关键字情况下,是否存在下一条相同关键字的观测
FIND_NEXT 在允许出现相同关键字情况下,寻找下一条相同关键字的观测
FIND_PREV 在允许出现相同关键字情况下,寻找前一条相同关键字的观测
REMOVEDUP 在允许相同关键字出现的情况下,在哈希表中移去当前关键字等数据
REPLACEDUP 在允许出现相同关键字情况下,使用新的数据代替当前关键字对应的数据等
SUMDUP 在允许出现相同关键字情况下,计算并返回当前关键字下的指定计数的变量和

由于哈希表的定义及操作的语法及使用语句较多,格式较新,下面我们通过一个例子来解释哈希表的定义及简单操作。
定义一个哈希表并对其进行ADD、CHECK、FIND、REMOVE、REPLACE、NUM_ITEMS等操作。

 

data hash_sample;
 input fruit$ amount;
 cards;
 apple  100
 orange 200
 tomato 300
 cherry 400
 cherry 500
 ;
run;


data _null_;

length fruit $10. amount 8.;
if _n_ = 1 then do ;

declare hash myhash (dataset:'hash_sample',duplicate:'r');/*定义一个名为myhash的哈希表,并把work.hash_sample的数据集映射到哈希表上;duplicate: "r"表示相同关键字时数据会不断代替,其结果是哈希表中只有相同关键字的最后*/
rc = ('fruit'); /*定义关键字段为fruit*/
rc = ('fruit','amount');/*定义数据

fruitamount,需要注意的是,这里若只定义amount变量,则哈希表中不存在fruit变量,而只是存在其对应的地址,当以需要引用哈希表输出的时候将忽略fruit变量。

*/
rc = ();/***定义完成*****/

call missing(fruit,amount);/*当未找到匹配值时,返回空值给指定变量。*/

end;
rc=(key:'cherry');/*查找是否存在key值为cherry的数据*/
if rc=0 then do; put fruit= amount= ;
end;
rc=(key:'tomato');/*检查是否存在key值为tomato的数据*/
if rc=0 then do;
  put 'tomato is exist';
  rc = (key:'tomato',data:'tomato',data:350);
end;
rc=(key:'tomato');
if rc=0 then do;
put 'new tomato' fruit= amount= ;
end;
(key:'peach',data:'peach',data:400);/****添加数据******/
rc=(key:'peach');
if rc=0 then do;
put 'new peach' fruit= amount= ;
end;
(key:'balabala',data:'balabala',data:600);/**查找并添加,若找到‘balabala’则不做任何操作,否则添加该条记录**/
rc = (key:'balabala');
if rc=0 then do;
put 'balbala' fruit= amount= ;
end;
totalitems = myhash.num_items;/*计算哈希表中观测的数量并赋值给totalitems。*/
put  totalitems;
(dataset:'out');
run;

输出后结果数据集:

程序解读:

把数据集(hash_simple)映射到哈希表,并在哈希表中做添加、修改等简单操作,最后输出哈希表。rc为接收返回值,程序中若操作成功则返回0,失败则返回非0。