基于标准的子集
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" 语句,该语句将增加数据集计数,输出到数据集,清除散列,并添加之前添加失败的当前行。
我想在每次计数变量等于 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" 语句,该语句将增加数据集计数,输出到数据集,清除散列,并添加之前添加失败的当前行。