SAS-使用宏拆分多个数据集的代码改进
SAS- Code improvement for spliting multiple dataset with macro
我使用以下代码在一个库中自动拆分数据集。
- 首先,我使用 proc sql 将所有数据集放入 table 并对其编号。
- 其次,我也是使用procsql读取每个dataset中的内容
顺序设置拆分规则。更具体地说,拆分过程
基于两个变量:date_l_ 和 _ric。显然,date_l_ 是一个
日期变量。 _ric 是一个标识名称的变量
股票。这一步的结果如下:
- 最后,我使用 %do j=1 %to &obs。拆分数据集。
以下是我的代码。
%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.);
但是,我遇到了如下所示的错误:
根据问题说明:如果 SAS 必须获取内存才能处理直接访问绑定库,并且内存已经耗尽,则 SASLOG 中可能会出现错误消息。
由于我有大约100个数据集并且包含各种数据和RIC(变量名),因此无法手动拆分数据集。在这种情况下,我该如何改进我的代码来改进这段代码呢?
这是磁盘 space 问题。 "I/O" 数据集错误往往不是因为内存问题,而是因为磁盘 space。您的数据集有很多重复值,这在压缩方面对您有好处。您想做的三件事:
1.将列长度设置为仅需要的长度
可以使用 attrib
或 length
语句为每个变量完成此操作。我发现有用的一种方法是在初始数据集上使用 %squeeze()
macro,将这些属性保存到单独的空数据集,然后使用 create table like
保留这些属性而不必 运行 %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
作为 set
语句中的第一个 table。
2。使用 compress
数据集选项
压缩数据集可以节省大量 space。 SAS 使用两种算法:一种适用于字符变量,一种适用于数字。对于您的情况,请同时尝试两者,看看哪个效果最好。
%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;
3。检查正在使用多少内存
打开系统选项fullstimer
以获得每个步骤所用内存量的详细视图。如果使用的内存太多,您将需要采用不同的方法来使用较少的总内存。
例如,您在单个数据步骤中输出所有内容。您可以将其转换为多个单独的数据步骤,而不是一个大的数据步骤。
您的 SAS 日志照片中的关键行是这样写的:
NOTE: Table WORK.TMP4 created, with 17329 rows and 2 columns.
你不能在一个数据步骤中创建一万七千个数据集。
你为什么要这样做?您将需要在多个数据步骤中执行此操作,或者更好地找到针对您的原始问题的不同解决方案。
我使用以下代码在一个库中自动拆分数据集。
- 首先,我使用 proc sql 将所有数据集放入 table 并对其编号。
- 其次,我也是使用procsql读取每个dataset中的内容 顺序设置拆分规则。更具体地说,拆分过程 基于两个变量:date_l_ 和 _ric。显然,date_l_ 是一个 日期变量。 _ric 是一个标识名称的变量 股票。这一步的结果如下:
- 最后,我使用 %do j=1 %to &obs。拆分数据集。
以下是我的代码。
%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.);
但是,我遇到了如下所示的错误:
由于我有大约100个数据集并且包含各种数据和RIC(变量名),因此无法手动拆分数据集。在这种情况下,我该如何改进我的代码来改进这段代码呢?
这是磁盘 space 问题。 "I/O" 数据集错误往往不是因为内存问题,而是因为磁盘 space。您的数据集有很多重复值,这在压缩方面对您有好处。您想做的三件事:
1.将列长度设置为仅需要的长度
可以使用 attrib
或 length
语句为每个变量完成此操作。我发现有用的一种方法是在初始数据集上使用 %squeeze()
macro,将这些属性保存到单独的空数据集,然后使用 create table like
保留这些属性而不必 运行 %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
作为 set
语句中的第一个 table。
2。使用 compress
数据集选项
压缩数据集可以节省大量 space。 SAS 使用两种算法:一种适用于字符变量,一种适用于数字。对于您的情况,请同时尝试两者,看看哪个效果最好。
%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;
3。检查正在使用多少内存
打开系统选项fullstimer
以获得每个步骤所用内存量的详细视图。如果使用的内存太多,您将需要采用不同的方法来使用较少的总内存。
例如,您在单个数据步骤中输出所有内容。您可以将其转换为多个单独的数据步骤,而不是一个大的数据步骤。
您的 SAS 日志照片中的关键行是这样写的:
NOTE: Table WORK.TMP4 created, with 17329 rows and 2 columns.
你不能在一个数据步骤中创建一万七千个数据集。 你为什么要这样做?您将需要在多个数据步骤中执行此操作,或者更好地找到针对您的原始问题的不同解决方案。