SAS 哈希对象总和
SAS Hash object sum
我想了解 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 的新手,所以我仍在研究这个 "Tick off answer" 系统...我觉得每个人都做出了贡献。
总之,经过大量的实验,我弄明白了是怎么回事-
基本上,每当调用 .sum() .replace() 时,求和计数器将重置为零。 这, 而不是真正的 replace() 等等 ,这就是为什么结果是这样的原因——sum() 重置了我的计数,所以 ref() 只是对前 2 个观察结果求和。
希望这是对大家有用的信息。如果其他人有任何见解,请分享。
我认为 T.REPLACE() 是您问题的一部分。我不知道这样做有什么好处,只有坏处。如果您将其注释掉,则 PUT _ ALL _ 会显示您想要的内容。令我惊讶的是(对 SAS 散列仍然是新手),我无法让 T.Output() 将 x_sum 变量写入输出数据集。希望其他人会插话。也许这些 suminc 蓄能器的处理方式不同?在下面,由于 PDV 有正确的数据,我切换到以正常的数据步骤方式写入输出数据集,而不是使用 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;
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;
您的问题是当您声明您的散列 table 时,您的密钥 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
问题在于您对 Replace() 的使用。来自文档(9.3 语言参考概念,使用散列对象):
This SUMINC tag instructs the hash object to allocate internal storage for maintaining a summary value for each key.
The summary value of a hash key is initialized to the value of the
SUMINC variable whenever the ADD or REPLACE method is used. The
summary value of a hash key is incremented by the value of the SUMINC
variable whenever the FIND, CHECK, or REF method is used.
我认为重要的一点是 "summary value" 不是 DATA 步变量 x_sum,或者 x_sum 作为数据变量存储在散列 table 中。它存储在散列 table 定义的数据之外。辅助信息实际上是密钥的一个属性。 (在我脑海中...)
如果你注释掉 replace(),你的代码可以工作(你在 PDV 中得到 x_sum 的正确值),但问题是 x_sum 永远不会写入哈希table。因此,您调用 replace() 将 x_sum 写入散列 table,导致不幸的副作用,即汇总值被初始化为 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;
我想了解 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 的新手,所以我仍在研究这个 "Tick off answer" 系统...我觉得每个人都做出了贡献。
总之,经过大量的实验,我弄明白了是怎么回事-
基本上,每当调用 .sum() .replace() 时,求和计数器将重置为零。 这, 而不是真正的 replace() 等等 ,这就是为什么结果是这样的原因——sum() 重置了我的计数,所以 ref() 只是对前 2 个观察结果求和。
希望这是对大家有用的信息。如果其他人有任何见解,请分享。
我认为 T.REPLACE() 是您问题的一部分。我不知道这样做有什么好处,只有坏处。如果您将其注释掉,则 PUT _ ALL _ 会显示您想要的内容。令我惊讶的是(对 SAS 散列仍然是新手),我无法让 T.Output() 将 x_sum 变量写入输出数据集。希望其他人会插话。也许这些 suminc 蓄能器的处理方式不同?在下面,由于 PDV 有正确的数据,我切换到以正常的数据步骤方式写入输出数据集,而不是使用 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;
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;
您的问题是当您声明您的散列 table 时,您的密钥 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
问题在于您对 Replace() 的使用。来自文档(9.3 语言参考概念,使用散列对象):
This SUMINC tag instructs the hash object to allocate internal storage for maintaining a summary value for each key. The summary value of a hash key is initialized to the value of the SUMINC variable whenever the ADD or REPLACE method is used. The summary value of a hash key is incremented by the value of the SUMINC variable whenever the FIND, CHECK, or REF method is used.
我认为重要的一点是 "summary value" 不是 DATA 步变量 x_sum,或者 x_sum 作为数据变量存储在散列 table 中。它存储在散列 table 定义的数据之外。辅助信息实际上是密钥的一个属性。 (在我脑海中...)
如果你注释掉 replace(),你的代码可以工作(你在 PDV 中得到 x_sum 的正确值),但问题是 x_sum 永远不会写入哈希table。因此,您调用 replace() 将 x_sum 写入散列 table,导致不幸的副作用,即汇总值被初始化为 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;