将sas程序拆分为多个程序,最后合并输出

时间:2018-02-04 15:53:42

标签: sas sas-macro

我创建了一个文件(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个不同进程的输出。

你能否提供我应该如何构建这个程序的框架,我有一些模糊的想法,但我相信我可以带走一些优雅的答案。

1 个答案:

答案 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)

但是,您实际上是应该注意的方案,并考虑可能在之前的运行或步骤中遗留的中间设置或数据集。