SAS-使用宏分割多个数据集的代码改进

时间:2016-10-31 19:56:58

标签: loops split macros sas out-of-memory

我使用以下代码在一个库中自动拆分数据集。

  1. 首先,我使用proc sql将所有数据集放入表中并对其进行编号。
  2. 其次,我还使用proc sql来读取每个数据集中的内容 为了设置拆分规则。更具体地说,分裂过程 基于两个变量:date_l_和_ric。显然,date_l_是一个 日期变量。而_ric是一个标识名称的变量 股票。此步骤的结果如下所示:
  3. enter image description here

    1. 最后,我使用%do j = 1%来& obs。拆分数据集。
    2. 以下是我的代码。

      %macro split(sourcelib=,source=,result=);
      proc sql noprint;  /*read datasets in a library*/
      create table mytables as
      select *
      from dictionary.tables
      where libname = &sourcelib 
      order by memname ;
      
      select count(memname) 
      into:numb 
      from mytables;
      
      %let numb=&numb.;  /*give a number to datasets in the library*/
      
      select memname
      into :memname1-:memname&numb.
      from mytables;
      quit;
      
      %do i=1 %to &numb.;
      proc sql noprint;
      create table tmp&i as
      select distinct date_l_, _ric
      from &source.&&memname&i;
      
      select count(*)
      into :obs
      from work.tmp&i.;
      
      %let obs=&obs.; /*read the variable 'date_l_' and '_ric' in each dataset*/
      
      select date_l_, _ric, catx("_", "&result.", substr(_ric, 1, 13), date_l_)
      into :date_l_1-:date_l_&obs., :ric1-:ric&obs., :setname1-:setname&obs.
      from work.tmp&i;
      quit;
      %end;
      
      data 
      %do j = 1 %to &obs.;   /*set rules for separated dataset*/
      &&setname&j
      %end;
      ;
      set
      %do i=1 %to &numb.;
      &source.&&memname&i
      %end;
      ; 
      select;
      %do j = 1 %to &obs.;
      when(_ric = "&&ric&i" and date_l_ = &&date_l_&i) output &&setname&j;
      %end;
      end;
      %mend;
      
      %split(sourcelib='DATA',source=DATA.,result=AXP.);
      

      但是,我遇到了如下错误: enter image description here 根据问题说明:如果SAS必须获取内存以处理直接访问绑定库,并且内存已经耗尽,则SASLOG中可能会出现错误消息。

      由于我有大约100个数据集并且禁止各种数据和RIC(变量名称),因此无法手动拆分数据集。在这种情况下,我如何改进我的代码来改进这段代码?

2 个答案:

答案 0 :(得分:1)

这是一个磁盘空间问题。 " I / O"数据集错误往往不是因为内存问题而是因为磁盘空间而发生。您的数据集有很多重复值,这在压缩方面对您有好处。你想做的三件事:

<强> 1。将列长度设置为仅需要

可以使用attriblength语句对每个变量执行此操作。我发现有用的方法是在初始数据集上使用%squeeze() macro,将这些属性保存到单独的空数据集,然后使用create table like保留这些属性,而不必运行{{1}再次。例如:

%squeeze()

如果您的完整数据集定期更新或覆盖,丢失属性,这将非常有用。使用/* Shrink the dataset */ %squeeze(everything, everything_squeezed); /* Save a copy of all these attributes in an empty dataset */ proc sql noprint; create table everything_attribs like everything_squeezed; quit; 作为everything_attribs语句中的第一个表。

<强> 2。使用set数据集选项

压缩数据集可以节省大量空间。 SAS使用两种算法:一种适用于字符变量,一种适用于数字。在你的情况下,尝试两者,看看哪个给出了最好的结果。

compress

第3。检查正在使用的内存量

打开系统选项%do i=1 %to &numb.; proc sql noprint; create table tmp&i(compress=yes) as select distinct date_l_, _ric from &source.&&memname&i; select count(*) into :obs from work.tmp&i.; %let obs=&obs.; /*read the variable 'date_l_' and '_ric' in each dataset*/ select date_l_, _ric, catx("_", "&result.", substr(_ric, 1, 13), date_l_) into :date_l_1-:date_l_&obs., :ric1-:ric&obs., :setname1-:setname&obs. from work.tmp&i; quit; %end; data %do j = 1 %to &obs.; /*set rules for separated dataset*/ &&setname&j(compress=yes) %end; ; set %do i=1 %to &numb.; &source.&&memname&i %end; ; select; %do j = 1 %to &obs.; when(_ric = "&&ric&i" and date_l_ = &&date_l_&i) output &&setname&j; %end; end; %mend; 以获取每个步骤使用的内存量的详细视图。如果使用的内存太多,则需要采用不同的方法来减少总内存。

例如,您在单个数据步骤中输出所有内容。您可以将其转换为多个单独的数据步骤,而不是一个大的步骤。

答案 1 :(得分:0)

SAS日志照片中的关键字是:

NOTE: Table WORK.TMP4 created, with 17329 rows and 2 columns.

您无法在一个数据步骤中创建17,000个数据集。 你为什么要这么做?您需要在多个数据步骤中执行此操作,或者更好地找到原始问题的不同解决方案。