我创建了一个文件(metadata.sas7bdat),它有100个条目,包含两列目录和sasdatasets。
Proc means data=abc.sas out=x;
Run;
假设我有sample.sas,它只能获取每个数据集的方法。
{{1}}
上面的sample.sas应该在元数据文件中的每个数据集上运行。现在我用非常传统的方式编写它,循环遍历元数据中的所有文件,并在每个文件上运行proc意味着并附加所有数据。最终数据集具有元数据中存在的所有文件的平均值。
我相信如果我可以将元数据文件分成4个部分,每个部分有(100/4 = 25个条目)并将其作为4个程序提交,最后合并所有4个程序的输出它将大大减少处理时间。 (想想10,000个条目,并假设有比proc处理更多的处理)。它只是我不知道用什么样的选项来提交它作为4个程序以及如何同步4个不同进程的输出。
你能否提供我应该如何构建这个程序的框架,我有一些模糊的想法,但我相信我可以带走一些优雅的答案。
答案 0 :(得分:0)
此问题似乎与Is it possible to loop over SAS datasets?
非常相似分为四个部分不会缩短整体处理时间。对于每个部分肯定。如果你认为整体上会有减少的处理,那么支持这个前提的测试或证据是什么?
当有一大组处理,P,分为步骤,p(1),p(2),... p(N)时,你需要构建一个可以存储中间结果的数据结构,以及在某些p(i)遇到错误后重新启动过程时不重复过去处理的规则,或先前尝试P停止在p(i)
考虑一下您的情况,您需要使用步骤键存储或累积中间方法。自然键是目录和文件名。
顶级调度程序为元数据中的每个项调用步骤宏。步骤宏在必要时执行流程详细信息,并以累积方式附加结果。
顶级:为元数据项分配每个步骤
%macro process_all (metadata=, results=);
data _null_;
set &metadata;
invoke = cats('%process_step(libname=',libname,',memname=',memname,",results=&results)");
put 'NOTE: ' _n_= invoke=;
call execute ('%nrstr(' || trim(invoke) || ')');
/* global parameter for checking testing 'restart' *
%if %symexist(test_param_1) %then %do;
if _n_ >= &test_param_1 then stop;
%end;
run;
%mend;
步骤级:一个元数据项的核心流程。如果之前完成,请跳过步骤,否则执行操作并累积结果。
%macro process_step(libname=, memname=, results=);
%local have_results;
%local step_done;
%let have_results = %sysfunc(exist(&results,data));
%let step_done = 0;
%if &have_results %then %do;
data _null_;
set &results; where libname="&libname" and memname="&memname";
call symput ('step_done', '1'); stop;
run;
%end;
%if &step_done %then %do;
%put NOTE: This step already done. &=libname &=memname;
%return;
%end;
proc delete data=_step_out;
proc means data=&libname..&memname noprint;
var height weight;
output out=_step_out(label="step output for &libname. . &memname.");
run;
data _step_out;
length libname $8 memname $32.;
set _step_out;
libname = symget('libname');
memname = symget('memname');
run;
proc append base=&results data=_step_out force;
run;
%mend;
测试方案的各种元数据配置
data _1 _2 _3 _4 _5 _6 _7 _8;
set sashelp.class;
run;
data configuration_1(keep=libname memname);
length libname $8 memname $32.;
libname = 'work';
do index = 1,2,3,7,8; memname='_'||cats(index); output; end;
run;
options mprint;
/*
* reset results to start from scratch
proc delete data=results_1;run;
*/
%let test_param_1 = 3; %* force stoppage after first three items;
%process_all(metadata=configuration_1, results=results_1)
%symdel test_param_1; %* force rerun of all to ignore first three already done items;
%process_all(metadata=configuration_1, results=results_1)
但是,您实际上是应该注意的方案,并考虑可能在之前的运行或步骤中遗留的中间设置或数据集。