楼主: Tigflanker
4291 10

[问答] 求助一个Hash Merge问题,基本但是想不明白 [推广有奖]

  • 8关注
  • 18粉丝

副教授

49%

还不是VIP/贵宾

-

威望
0
论坛币
2321 个
通用积分
9.8528
学术水平
179 点
热心指数
194 点
信用等级
167 点
经验
27443 点
帖子
622
精华
0
在线时间
851 小时
注册时间
2011-3-27
最后登录
2023-5-14

120论坛币
求助各位老师朋友一个Hash的问题,感觉很基础,但是我确实想不明白。

细节上是关于if 0 then set <dataset>;和普通length <vars>;的差异。

例如我就想做一个小表和大表的普通条件merge。

if a和b匹配上,就把b表中的d merge给大表a。

用length语句做声明,结果正确;用if 0 then set做编译,结果不正确。

感觉以前也这样用过不少,但是没发现问题,很奇怪。。
  1. data a;
  2.   input a b c;
  3.   cards;
  4. 1 1 11
  5. 1 2 22
  6. 1 3 33
  7. 2 1 44
  8. 2 2 55
  9. 2 3 66
  10. ;run;

  11. data b;
  12.   input a b d;
  13.   cards;
  14. 1 2 222
  15. 2 2 555
  16. ;run;

  17. data c;
  18. /*  length a b d 8;*/
  19.   if 0 then set b;
  20.   if _n_ = 1 then do;
  21.     dcl hash h(dataset:"b");
  22.         h.definekey("a","b");
  23.         h.definedata(all:'y');
  24.         h.definedone();
  25.         call missing(d);
  26.   end;
  27.   
  28.   set a;
  29.   rc = h.find();
  30. run;
复制代码

最佳答案

老师她摸我 查看完整内容

1.LENGTH和IF 0 THEN SET都是定义变量的属性,区别在于LENGTH有个CALL MISSING,这是因为通常MAIN DATASET没有我们要MERGE的变量(D),所以要用一个CALL MISSING或者赋值语句来避免LOG中出现未初始化的提示。 2. 对于两种定义方法出现的结果不同,主要还得从PDV来理解,因为在HASH OBJECT中,如果没有匹配成功(H.FIND() NE 0), PDV中的MERGE变量(D)是不会重置的,这点与MERGE方法不同(BY GROUP一改变则PDV就重置),此时MER ...
关键词:Merge HASH 不明白 Has Defined 朋友

回帖推荐

bobguy 发表于7楼  查看完整内容

A variable from a sas data set will retain automatically. The variable d is from a SAS data set b in your case, so it retains its value. In this case, using length or set depends what you need. Here is an example to help you understand it better. data t1; a=1;b=2;c=3;d=4; run; data a; input a b c; if a=1 then d=c; cards; 1 1 11 1 2 22 1 3 33 ...
Bye SAS.
若有缘,能重聚。
匿名网友
沙发
匿名网友  发表于 2014-12-9 22:21:08 |坛友微信交流群
1.LENGTH和IF 0 THEN SET都是定义变量的属性,区别在于LENGTH有个CALL MISSING,这是因为通常MAIN DATASET没有我们要MERGE的变量(D),所以要用一个CALL MISSING或者赋值语句来避免LOG中出现未初始化的提示。
2. 对于两种定义方法出现的结果不同,主要还得从PDV来理解,因为在HASH OBJECT中,如果没有匹配成功(H.FIND() NE 0), PDV中的MERGE变量(D)是不会重置的,这点与MERGE方法不同(BY GROUP一改变则PDV就重置),此时MERGE变量的值就是最近一次MATCH成功的值了。个人习惯用IF 0 THEN SET这种方法来LOAD变量的属性,因为我们在没有匹配成功的时候,通常都要对MERGR变量(D)进行赋值(特定值或MISSING)。
所以在你的例子中,对于两种定义变量属性的方法,你只要在RC=H.FIND()前任意位置加上一个CALL MISSING(D),或者在RC=H.FIND()后对没有匹配的记录进行赋值(IF RC NE 0 THEN D=.)结果就一样了。
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
Tigflanker + 5 + 3 + 3 + 3 谢猫兄,我理解下。。

总评分: 论坛币 + 5  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

使用道具

藤椅
Eternal0601 发表于 2014-12-9 23:12:51 |只看作者 |坛友微信交流群
个人认为是由于set dataset中的变量实际上存在一个retain的作用,当你hash中找到对应key variables a b的时候,会把hash中的data part变量d返回到data部中,d 存在于set dataset中,所以会自动retain,当你碰到下次的hash key的时候,再次返回的值会将之前的d给覆盖掉,然后继续retain, 所以在用if 0 set时,要对没有找到key 时候,data part进行call missing处理
data c3;
/*  length a b d 8;*/
  if 0 then set b;
  if _n_ = 1 then do;
    dcl hash h(dataset:"b");
        h.definekey("a","b");
        h.definedata(all:'y');
        h.definedone();
        call missing(d);
  end;
  
  set a;
  if h.find() ne 0 then call missing(d);
run;
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
Tigflanker + 5 + 3 + 3 + 3 感谢,见回复。

总评分: 论坛币 + 5  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

使用道具

板凳
jl60156 发表于 2014-12-10 00:25:18 |只看作者 |坛友微信交流群
Basically they do similar job. when using length , no need  call missing.
if using if 0 then set you need call missing.
in your code , you might put call missing (d) after if _n_=1 then do; end;
just call missing(d) before set a;
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
Tigflanker + 5 + 3 + 3 + 3 Thanks, I agree with you.

总评分: 论坛币 + 5  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

使用道具

报纸
我爱大脚丫 发表于 2014-12-10 08:42:12 |只看作者 |坛友微信交流群




使用道具

地板
Tigflanker 发表于 2014-12-10 10:15:14 |只看作者 |坛友微信交流群
Eternal0601 发表于 2014-12-9 23:12
个人认为是由于set dataset中的变量实际上存在一个retain的作用,当你hash中找到对应key variables a b的时 ...
谢谢。

比较赞同,昨天想了一下;if 0 then set时不需要用call missing,而length需要。

感觉上好像是length仅在data步编译时读取信息、而这个if 0 then set是在编译和每一步pdv执行时都在预读而不执行。

所以这个set句起到了retain作用,find()仅是做了个刷新作用。

这也是我的个人猜测。

另外我这真有点不知道,这以后假说用hash做merge,还怎么把hash的数据集信息铺垫在PDV中,难道是1by1的length进去。。这以后再也不敢愉快的使用hash来接dataset了。

使用道具

7
bobguy 发表于 2014-12-10 11:41:37 |只看作者 |坛友微信交流群
A variable from a sas data set will retain automatically.

The variable d is from a SAS data set b in your case, so it retains its value.

In this case, using length or set depends what you need.

Here is an example to help you understand it better.

data t1;
  a=1;b=2;c=3;d=4;
  run;

data a;
      input a b c;
          if a=1 then d=c;
      cards;
    1 1 11
    1 2 22
    1 3 33
    2 1 44
    2 2 55
    2 3 66
    ;run;

        proc print;run;


data a;
     if 0 then set t1;
      input a b c;
          if a=1 then d=c;
      cards;
    1 1 11
    1 2 22
    1 3 33
    2 1 44
    2 2 55
    2 3 66
    ;run;

        proc print;run;
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
Tigflanker + 5 + 3 + 3 + 3 This is what I want.

总评分: 论坛币 + 5  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

使用道具

8
老师她摸我 发表于 2014-12-10 12:24:13 |只看作者 |坛友微信交流群
Tigflanker 发表于 2014-12-10 10:15
谢谢。

比较赞同,昨天想了一下;if 0 then set时不需要用call missing,而length需要。
这里和这个SET应该没有关系,因为IF 0 THEN SET这个语句只编译不会执行,所以这个语句主要是读取变量名和变量属性,不会读记录的,读取后PDV中的变量值都为空。

如data demo; if 0 then set sashelp.class; run;,得到一条变量值都为空的记录。

建议你用IF 0 THEN SET啊,这样就不用1BY1的LENGTH啊,只是因为没有匹配成功时PDV不会重置,所以注意这一点就一样可以愉快地使用呢!

使用道具

9
Tigflanker 发表于 2014-12-10 12:35:51 |只看作者 |坛友微信交流群
bobguy 发表于 2014-12-10 11:41
A variable from a sas data set will retain automatically.

The variable d is from a SAS data set b ...
Looks as if I didn't understand 'if 0 then set' clearly.

So I have another question need to consult.

If I really want to merge two table by a group of key variables.
(But two tables contain many different variales.)

What should I handle?

I only have an idea in my mind, to use dictionary's information help to write LENGTH and CALL MISSING statments.
Which may be an awkward way.

Thanks for your above reply first.

使用道具

10
Tigflanker 发表于 2014-12-10 13:00:17 |只看作者 |坛友微信交流群
老师她摸我 发表于 2014-12-10 12:24
这里和这个SET应该没有关系,因为IF 0 THEN SET这个语句只编译不会执行,所以这个语句主要是读取变量名和 ...
if 0 then set;以前我一直用来从spec做个空数据集来刷final数据集的属性

我这会终于明白个事情:为什么当spec(属性空数据集)有而final没有的变量,刷过属性后,那些没有的变量会以missing value的形式dummy进入。

那现在想想如果一定要用hash来做整集A和B的merge,想来用 if 0 then set B; 先为hash declare做铺垫,还得在那步之前用sql except做一个 B - A - keys 的变量名宏变量用于结合find()做一下call missing。

若是这么麻烦的话,我倒觉得不建议用hash来做完整数据集的merge了。所以我还是决定用hash来做判断和重命名data形式更新pdv以后。

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-24 03:15