Sas 如何按一定顺序读取两个数据集?
假设我有两个数据集A和B:Sas 如何按一定顺序读取两个数据集?,sas,datastep,Sas,Datastep,假设我有两个数据集A和B: Data A; input data $; datalines; A1 A2 A3 ; run; Data B; input data $; datalines; B1 B2 B3 ; run; 我不想生成具有特定顺序的数据集,如下所示: A1 B1 B2 B3 A2 B1 B2 B3 A3 B1 B2 B3 如何从数据集A和B按数据步执行,而不使用点= 我尝试过这种方法: DATA WRONG_ANSWER; SET A; OUTPUT; DO i = 1
Data A;
input data $;
datalines;
A1
A2
A3
;
run;
Data B;
input data $;
datalines;
B1
B2
B3
;
run;
我不想生成具有特定顺序的数据集,如下所示:
A1
B1
B2
B3
A2
B1
B2
B3
A3
B1
B2
B3
如何从数据集A和B按数据步执行,而不使用点=
我尝试过这种方法:
DATA WRONG_ANSWER;
SET A;
OUTPUT;
DO i = 1 to 3;
SET B;
OUTPUT;
END;
RUN;
结果是:
A1
B1
B2
B3
A2
看起来像是B的文件结束指示符终止此数据步骤
我还用POINT=尝试了另一种方法,得到了正确的结果。但是,由于从B访问特定obs时需要大量I/O时间,因此这种方法非常缓慢:
DATA WRONG_ANSWER;
SET A;
OUTPUT;
DO i = 1 to 3;
SET B POINT=i; //this is the only different from above
OUTPUT;
END;
RUN;
假设有几件事,最快的方法可能是哈希迭代器解决方案。假设:
- 数据集B足够小,可以在内存中容纳(一次)
- 要么您不关心结果数据集中数据集B行的顺序,要么您的键变量具有升序或降序,或者您可以构造键顺序变量
- 数据集B可以定义一个键,使其包含唯一的行,或者您可以使用“multidata:yes”(具有足够新的SAS版本以支持该功能)
data want;
if 0 then set b;
if _n_=1 then do;
declare hash b_hash(dataset:'b', ordered:'a');
b_hash.defineKey('data');
b_hash.defineData('data');
b_hash.defineDone();
declare hiter b_iter;
b_iter = _new_ hiter('b_hash');
end;
set a;
output;
rc = b_iter.first();
do while (rc=0);
output;
rc = b_iter.next();
end;
run;
根据您的用例,您可能希望通过宏系统和/或dictionary.columns查询构造defineData
调用,以避免对列名进行硬编码
这比点快得多;与基线相比:
data want_point;
set a;
output;
do _n_ = 1 to nobs_b;
set b point=_n_ nobs=nobs_b;
output;
end;
run;
- 对于大a、1e7行和小B、3行,需要约10秒实时/8秒CPU时间(基本上不超过总写入时间),而基线点需要100秒实时/12秒CPU时间
- 使用较小的a点,效率会有所提高,但哈希仍然优于a点(虽然只是稍微好一点,可能不值得在编码难度上有所不同)。两种方法的写入时间都接近10秒,以写出1e4 A/1e3 B组合(这将生成与第一个文件大小相似的文件)
- 对于小a和大B(3行a,1行7行B),哈希需要更长的时间,因为它有昂贵的首次设置成本;哈希解决方案为67秒(28秒CPU),而point为65秒(17秒CPU)
因此,如果您有一个大数据集,并且要将它与一个小数据集重复组合,则建议使用哈希。如果两个数据集大小相似,或者重复设置的数据集更大,则point可能与您得到的一样好(考虑到维护哈希的更高难度)。好问题(现在)。我很好奇是否有一种基于集合的方法。我将发布一个不基于集合的方法,但希望看到使用集合(而不是点)的替代方法。当然,随机访问(
点
)是我在本例中自然使用的方法。在您的实际案例中,了解数据集的相对大小可能会有所帮助。A和B数据集中都有大约2百万个OB。这不是会产生约4万亿行吗?(2mil*2mil)。难怪它很慢。不管你想做什么,把两个200万行的表变成一个4万亿行的表听起来不是一个好方法。你提供的第二种方法还有一点,这种方法怎么能比我上次的方法更快?有什么重要的东西我没有注意到吗?第二种方法是点法-基线法(即你从中进行比较的方法)。我用hash测试了它,并证明它有时在性能上是完美的,有时不是。