我有以下示例代码:
`data hh;
keyx=1; xx=21;output;
keyx=3; xx=23;output;
keyx=4; xx=24;output;
keyx=5; xx=25;output;
run;
data tbl;
keyx=1;output;
keyx=2;output;
keyx=4;output;
keyx=5;output;
keyx=1;output;
keyx=6;output;
run;
data tbl_h_bezset;
length xx 8.;
if _N_=1 then do;
/*if 0 then set hh;*/
declare hash hh(dataset:'hh');
hh.definekey('keyx');
hh.definedata('xx');
hh.definedone();
end;
set tbl;
rc=hh.find();
run;
data tbl_h_set;
/*length xx 8.;*/
if _N_=1 then do;
if 0 then set hh;
declare hash hh(dataset:'hh');
hh.definekey('keyx');
hh.definedata('xx');
hh.definedone();
end;
set tbl;
rc=hh.find();
run;`
我发现很难理解结果的差异。 tbl_h_bezset 使用长度语句将 xx 包含在 PDV 中。生成的数据集具有 find() 方法的正确匹配项和不匹配的缺失值。但是,如果我使用“if 0 then set”以便将 xx 包含在 PDV 中(而不是长度语句),我会在 xx 变量中得到错误匹配而不是缺失值。看起来 sas 从上一行(找到 mach 的最后一行)获取 xx 值。我想我以某种方式明白为什么 tbl_h_set 输出它输出的内容。 “如果 0 则设置”在 PDV 向量中创建变量。在 X 行中已找到匹配项。在第 X+1 行中没有匹配项,但由于 tbl 数据集不涉及 xx 变量,PDV 向量使用前一行的值,该值尚未在 PDV 中清除。我说得对吗?而且,更重要的是,为什么使用 LENGTH 语句的 tbl_h_bezset 每次都会产生正确的匹配结果。
我希望在您的帮助下我能得到一些澄清。
我已经尝试通过互联网和 stackoverflo 论坛进行搜索。我测试了多种方法,但我无法理解机制上的差异。
问得好。在使用哈希对象时,了解非常非常重要。
关键在于 SAS Data Step 何时自动将变量设置为缺失的差异。您可以阅读当变量值被 SAS 自动设置为缺失时中的文档。尤其是最后一部分读取 SAS 数据集时很重要。
长处的缺点是Set Statement仅在DATA步骤的第一次迭代之前将变量值设置为缺失(不考虑By Statement的情况)。在通常情况下这通常就足够了,Set 语句在下一次迭代中读取另一个值,依此类推。
在
if 0 then set
的情况下,如果哈希对象中没有匹配项,则由您来确保值丢失。因此,您经常会看到 if 0 then set
语句后跟 Call Missing Statement。
data tbl_h_set;
if _N_ = 1 then do;
declare hash hh(dataset:'hh');
hh.definekey('keyx');
hh.definedata('xx');
hh.definedone();
end;
set tbl;
if 0 then set hh;
call missing(xx);
rc=hh.find();
run;
另一方面,当使用Length Statement时,变量值is在每个数据步骤迭代开始时自动设置为缺失。
data tbl_h_set;
if _N_ = 1 then do;
declare hash hh(dataset:'hh');
hh.definekey('keyx');
hh.definedata('xx');
hh.definedone();
end;
set tbl;
length xx 8.;
rc=hh.find();
run;
两种方法各有利弊。
if 0 then set
方法的主要优点是您无需提前知道在 PDV 中创建的变量的长度。这是自动继承的。