SAS Hash对象总和

时间:2015-05-17 23:35:12

标签: sas

我试图了解SAS Hash对象的sum()函数。根据我的理解,suminc:定义变量 SAS散列对象跟踪,而sum()将总结该变量的值。

假设我有数据集

data sample;
    input id x;
    datalines;
1 350
1 220
1 300
2 300
2 500
;
run;

我希望汇总

id x_sum
2  800
1  870

但是,我的哈希码:

data _null_;
    set sample end= done;

    length x_sum 8;

    if _N_ = 1 then 
    do;
        declare hash T(suminc:"x");
        T.definekey("id");
        T.definedata("id");
        T.definedata("x_sum");
        T.definedone();
    end;


    T.ref();

    T.sum(sum:x_sum);

    put _all_;


    T.replace();

    if done then T.output(dataset: "my_set");

run;

输出:

id x_sum
2  800
1  520

作为数据集和日志:

done=0 id=1 x=350 x_sum=350 _ERROR_=0 _N_=1
done=0 id=1 x=220 x_sum=570 _ERROR_=0 _N_=2
**done=0 id=1 x=300 x_sum=520 _ERROR_=0 _N_=3**
done=0 id=2 x=300 x_sum=300 _ERROR_=0 _N_=4
done=1 id=2 x=500 x_sum=800 _ERROR_=0 _N_=5

任何人都可以向我解释发生了什么吗?

所有评论后更新

大家好,我对Stack Overflow来说是全新的,所以我还在弄清楚这个"剔回答案"系统......我觉得每个人都有所贡献。

无论如何,经过大量的实验,我弄清楚发生了什么 -

基本上,每当调用 .sum() .replace()时,总和计数器都会重置为零。这个,并没有真正替换()等等,这就是为什么结果是这样的 - sum()重置我的计数,所以ref()只是总结前两个观察结果。

希望这对每个人都是有用的信息。如果其他人有任何见解,请分享。

4 个答案:

答案 0 :(得分:2)

问题是你使用Replace()。从文档(9.3语言参考concpets,使用哈希对象):

  

此SUMINC标记指示哈希对象分配内部存储以维护每个键的汇总值。   散列键的汇总值初始化为。的值   每当使用ADD或REPLACE方法时,SUMINC变量。该   散列键的汇总值增加SUMINC的值   每当使用FIND,CHECK或REF方法时变量。

我认为重要的一点是"汇总价值"不是数据步骤变量x_sum,或x_sum存储为哈希表中的数据变量。它存储在哈希表的定义数据之外。它的辅助信息实际上是密钥的一个属性。 (在我脑海里......)

如果你注释掉replace(),你的代码就可以工作(你在PDV中得到x_sum的正确值),但问题是x_sum永远不会被写入哈希表。因此,您调用replace()将x_sum写入哈希表,从而导致汇总值初始化为x值的不幸副作用。我认为解决方法的答案是在调用replace()之前分配x = x_sum。这样,当replace()将汇总值重新初始化为x的值时,x保存当前汇总值。我很难说出来,但看到下面只添加了一个陈述。

data _null_;
  set sample end= done;

  length x_sum 8;

  if _N_ = 1 then 
  do;
    declare hash T(suminc:"x");
    T.definekey("id");
    T.definedata("id");
    T.definedata("x_sum");
    T.definedone();
  end;
  T.ref();
  T.sum(sum:x_sum);
  put _all_;

  x=x_sum;  *Replace method will initialize the summary value to x! ;

  T.replace();
  if done then T.output(dataset: "my_set");
run;

答案 1 :(得分:0)

我认为T.REPLACE()是你问题的一部分。我不知道会做什么好事,只有坏事。如果您将其注释掉,则PUT _ ALL _显示您想要的内容。令我惊讶的是(SAS散列的新手),我无法让T.Output()将x_sum变量写入输出数据集。希望其他人可以加入。也许这些suminc累加器的处理方式不同?在下面,由于PDV具有正确的数据,我切换到以正常DATA步骤方式写入输出数据集,而不是使用output()

data my_set(keep=id x_sum);
  set sample;
  by id;

  if _N_ = 1 then 
  do;
    declare hash T(suminc:"x");
    T.definekey("id");
    T.definedata("x");
    T.definedone();
  end;

  T.ref();

  T.sum(sum:x_sum);

  put _all_;

  if last.id;
run;

答案 2 :(得分:0)

Maybe you can try these codes:
data _null_;

length x_sum 8;

if _N_ = 1 then 
do;
    declare hash T(suminc:"x");
    T.definekey("id");
    T.definedata("id");
    T.definedata("x_ct","x_sum");
    T.definedone();
end;

do until(done);
  set sample end = done;
  if t.find() ^= 0 then do;
     x_ct = 0;
     x_sum = 0;
  end;
  x_ct ++ 1;
  x_sum ++ x;
  t.replace();
 end;
 t.output(dataset:'want');
 stop;
run;

答案 3 :(得分:0)

您的问题是,当您重新声明哈希表时,您的密钥ID对于每条记录都不是唯一的。您可以通过包含多数据方法来修复它:multidata:"yes"

if _N_ = 1 then 
do;
    declare hash T(suminc:"x", multidata:"yes");
    T.definekey("id");
    T.definedata("id");
    T.definedata("x_sum");
    T.definedone();
end;

这给出了:

done=0 id=1 x=350 x_sum=350 _ERROR_=0 _N_=1
done=0 id=1 x=220 x_sum=570 _ERROR_=0 _N_=2
**done=0 id=1 x=300 x_sum=870 _ERROR_=0 _N_=3**
done=0 id=2 x=300 x_sum=300 _ERROR_=0 _N_=4
done=1 id=2 x=500 x_sum=800 _ERROR_=0 _N_=5