Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/184.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sas 如何按一定顺序读取两个数据集?_Sas_Datastep - Fatal编程技术网

Sas 如何按一定顺序读取两个数据集?

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

假设我有两个数据集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 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测试了它,并证明它有时在性能上是完美的,有时不是。