基于标准的子集

Subset based on a criteria

我想在每次计数变量等于 1 时对我的数据集(使用 sas)进行子集化。例如,以下数据集将分成两个数据集:

Over Ball      Bowling    Runs_scored Count 
39   1           Ali        1          1
39   2           Ali        1          2
39   3           Ali        2          3
39   4           Ali        1          4
39   5           Ali        1          5
39   6           Ali        1          6
36   1           Anderson   1          1
36   2           Anderson   1          2
36   3           Anderson   1          3
36   4           Anderson   0          4
36   6           Anderson   0          6

注意:即使上面 table 中每个投球手的最终计数都可以被 6 整除,但在实际(完整)数据集中并非如此。

我知道这个任务需要一个宏,但不知道从哪里开始。

谢谢, 安琪

要分隔数据集,请在数据语句中使用两个数据集名称。并使用output直接输出;

data set1 set2;
    set input;
    if count = 1 then output set1;
    else output set2;
run;

所以这意味着对于每个计数 = 1,添加一个分隔符并导出一个新数据集。

data test2;
    set test;
    retain n_count = 0;
    if count = 1 then n_count = n_count + 1;
run;
*calculate how many count = 1 in the dataset;
proc sql;
    select max(n_count) into :total trimmed
    from test2;
quit;

 %macro sep;
     %do i = 0 %to &total.;
        data sep_&i.;
            set test2;
            where n_count = &i.;
        run;
     %end;
  %mend;

  %sep;

正在创建 Test/Sample 数据集

data test;
infile datalines dlm=',';
input Over : 8.
      Ball : 8.
      Bowling : .
      Runs_scored : 8.
      Count : 8.
;
datalines; 
39,1,Ali,1,1
39,2,Ali,1,2
39,3,Ali,2,3
39,4,Ali,1,4
39,5,Ali,1,5
39,6,Ali,1,6
36,1,Anderson,1,1
36,2,Anderson,1,2
36,3,Anderson,1,3
36,4,Anderson,0,4
36,6,Anderson,0,6
;
run;

选择不同的轮数(据我了解板球,每个轮数都以“1”开头,这就是您要寻找的)和轮数

proc sql noprint;
select distinct over into: overs separated by "," from test;
select count(distinct over) into :numOfOvers from test;
quit;

为每个以上创建一个单独的数据集

%macro overnew();
 %do i=1 %to &numOfOvers.;

data over_%sysfunc(scan("&overs.",&i.,","));
set test;
where over=%sysfunc(scan("&overs.",&i.,","));
run;

%end;
%mend;

%overnew;

还有一个变体,它不使用宏,而是使用调用执行。首先创建一个与@neoman 相同的唯一 OVERS 列表,然后使用调用执行来生成数据集。

data test;
infile datalines dlm=',';
input Over : 8.
      Ball : 8.
      Bowling : .
      Runs_scored : 8.
      Count : 8.
;
datalines; 
39,1,Ali,1,1
39,2,Ali,1,2
39,3,Ali,2,3
39,4,Ali,1,4
39,5,Ali,1,5
39,6,Ali,1,6
36,1,Anderson,1,1
36,2,Anderson,1,2
36,3,Anderson,1,3
36,4,Anderson,0,4
36,6,Anderson,0,6
;
run;

*Get all the unique overs in the list;
proc sql noprint;
create table test_unique as
select distinct over
from test
order by over;
run;

*create the call execute string to split the dataset;
data _null_;
set test_unique;

str1="data over"||put(over, z3. -l)||";";
str2=cats("set test (where=(over=",over,"));run;");
str3=cats(str1, str2);
call execute(str3);
run;

这是一种执行此操作的方法,您不必多次循环遍历数据集。它也不使用宏,你不需要知道在运行它之前有多少次。

data _null_;
    set have end=done;
    if _n_=1 then do;
        declare hash h_out(ordered:"ascending");
        h_out.defineKey("count");
        h_out.defineData("over", "ball", "bowling", "runs_scored", "count");
        h_out.defineDone();
    end;

    if h_out.add() ne 0 or done then do;
        ds_count + 1;
        h_out.output(dataset: cats('want', ds_count));
        h_out.clear();
        h_out.add();
    end;
run;

这是通过创建一个散列对象来存储每个结束,然后当它到达结束或文件结束时,对象被写到数据集。
第二个 "if" 语句尝试将行添加到散列对象。由于我们使用 "count" 作为键,如果已经存在 "count" 的重复值(即 count=1),则此添加将失败。这将触发内部 "if" 语句,该语句将增加数据集计数,输出到数据集,清除散列,并添加之前添加失败的当前行。