【问题标题】:how to split large dataset as quickly as possible如何尽快拆分大数据集
【发布时间】:2019-04-04 17:50:13
【问题描述】:

我有一个非常大的数据集,大小为 1T,我需要将其快速拆分为多个子数据集。

以下是分割数据集的传统方式:

Data d1 d2...dn;
Set raw_dataset;
if condition1 then output d1;
else if condition2 then output d2;
...
else if conditionN then output dn;
run;

但是对我来说还是太慢了!!
有什么方法可以加快这个过程吗?

【问题讨论】:

  • 根据条件,您可以向原始数据集添加索引。
  • 太慢了怎么办?当您“中断”提交时,您让拆分运行多长时间?数据集中有多少行和变量?你要分裂多少?你能举一个分割标准的例子吗?你在什么硬件上? raw_dataset 在本地驱动器上吗?您正在写入网络或云目的地吗?为什么你觉得你需要拆分数据……你能适当地索引数据集以快速检索相关子集吗?您是否检查过系统事件查看器的磁盘 I/O 错误?
  • 您是否有权访问 SPDE libname 引擎或 SAS/CONNECT?这些中的任何一个都可以用来获得某种程度的并行性。
  • 你试过压缩=输出数据集吗?
  • 过滤条件有多复杂?有时数据集选项或其他方法更有效。

标签: sas


【解决方案1】:

可以使用下面的宏,只需输入两个参数 1.要拆分的输入数据集 2. 在每个数据集中输入您需要的最大观测值

options merror mprint symbolgen mlogic;

/****CHANGE PATH for input DS location****/
libname inp "Y:\InputDS";
libname outp "Y:\OutputDS";

data inp_ds;
 set inp.input_sample; /****CHANGE Input DS****/
run;

proc sql noprint;
select count(*) into: total_obs from inp_ds;
quit;

%let max_obs=20000; /****CHANGE max number of OBS in a split DS****/
%let split_ds_num_temp=%sysfunc(int(&total_obs/&max_obs));
%let remainder= %sysfunc(mod(&total_obs,&max_obs));

data find_num;
 if &remainder>0 then split_ds_num=&split_ds_num_temp+1;
 else split_ds_num=&split_ds_num_temp;
 call symput('no_of_splits',split_ds_num);
run;

%macro split(i,inds);
data outp.out&i;
 set &inds;
 %if &i=1 %then 
 %do;
    If _N_>=1 and _N_<=&max_obs Then Output;
 %end;
 %else %if &i>1 %then
 %do;
    If _N_ >=(&max_obs*(&i-1))+1 and _N_<=&max_obs*&i Then Output;
 %end;
run;
%mend split;

data initiate_macro;
do i = 1 to &no_of_splits;
    call execute('%split('||i||', inp_ds)');
end;
run;

这将创建多个输出数据集:out1 out2... outn ..取决于程序中提到的输出目录路径中的观察数

【讨论】:

    【解决方案2】:

    如果你不想使用条件,我可以和你分享这个我使用了 3 年的宏:

    %macro partitionner(Library=, Table=, nb_part=, nblig=, tabIntr=);
    data 
        %do i=1 %to &nb_part; 
            &Library..&tabIntr.&i. 
         %end;
    ; 
          set &Library..&Table.; 
    
          %do i=1 %to %eval(&nb_part-1); 
             if _n_ >= %eval(1+(&i.-1)*&nblig.) and _n_ <= %eval(&i.*&nblig.) 
             then output &Library..&tabIntr.&i.; 
          %end; 
          if _n_>=%eval((&i.-1)*&nblig+1) then output &lib..&tabIntr.&nb_part.; 
       run;
    %mend partitionner;
    

    在哪里:

    • 库:要拆分的表所在的库的名称和 结果。
    • 表:要拆分的表的名称。
    • nb_part : 拆分结果的表数。
    • nblig : 每个输出表中的行数。
    • tabIntr : 输出的表名(前缀)。

    示例:

    bigTable 有 100 行,位于 LIBRA 库中。想把它分成4张表,每张33行。

    %partitionner(Library=LIBRA, Table=bigTable, nb_part=4, nblig=33, tabIntr=smalTable);
    

    结果是:

    • smalTable1 有 33 个观察值。
    • smalTable2 有 33 个观察值。
    • smalTable3 有 33 个观察值。
    • smalTable4 有 1 个观察值。

    【讨论】:

      猜你喜欢
      • 2018-12-10
      • 2018-09-07
      • 2016-08-23
      • 2020-05-07
      • 2014-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多