我试图了解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()只是总结前两个观察结果。
希望这对每个人都是有用的信息。如果其他人有任何见解,请分享。
答案 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