我正在尝试检测包含第一年龄和第二年龄之间差异的组大于5.例如,如果我有以下数据,grp=1
中年龄之间的差异为39,所以我想要在单独的数据集中输出该组。同样适用于grp 4.
id grp age sex
1 1 60 M
2 1 21 M
3 2 30 M
4 2 25 F
5 3 45 F
6 3 30 F
7 3 18 M
8 4 32 M
9 4 18 M
10 4 16 M
我最初的想法是按grp
对它们进行排序,然后使用if first.grp then do;
之类的内容获得年龄之间的绝对值。但我不知道如何按组分获得第一年龄和第二年龄之间的绝对值,或者实际上我不知道该如何开始这个。
提前致谢。
答案 0 :(得分:2)
这是我认为有效的一种方式。
data have;
input id $ grp $ age sex $;
datalines;
1 1 60 M
2 1 21 M
3 2 30 M
4 2 25 F
5 3 45 F
6 3 30 F
7 3 18 M
8 4 32 M
9 4 18 M
10 4 16 M
;
proc sort data=have ;
by grp descending age;
run;
data temp(keep=grp);
retain old;
set have;
by grp descending age;
if first.grp then old=age;
if last.grp then do;
diff=old-age;
if diff>5 then output ;
end;
run;
Data want;
merge temp(in=a) have(in=b);
by grp ;
if a and b;
run;
答案 1 :(得分:1)
我会使用PROC TRANSPOSE,因此可以轻松比较每组中的值。例如:
data groups1;
input id $ grp age sex $;
datalines;
1 1 60 M
2 1 21 M
3 2 30 M
4 2 25 F
5 3 45 F
6 3 30 F
7 3 18 M
8 4 32 M
9 4 18 M
10 4 16 M
;
run;
proc sort data=groups1;
by grp; /* This maintains age order */
run;
proc transpose data=groups1 out=groups2;
by grp;
var age;
run;
使用转置数据,您可以做任何您喜欢的比较(我无法从您的问题中确切地知道您想要什么,所以我只是比较前两个年龄段):
/* With all ages of a particular group in a single row, it is easy to compare */
data outgroups1(keep=grp);
set groups2;
if abs(col1-col2)>5 then output;
run;
在这种情况下,这将是我为每个组创建单独数据集的首选方法,该数据集满足应用的任何条件(动态生成和包含代码):
/* A separate data set per GRP value in OUTGROUPS1 */
filename dynacode catalog "work.dynacode.mycode.source";
data _null_;
set outgroups1;
file dynacode;
put "data grp" grp ";";
put " set groups1(where=(grp=" grp "));";
put "run;" /;
run;
%inc dynacode;
答案 2 :(得分:0)
如果你只是在第1和第2年龄之间的差异,那么以下代码是一种相当简单的提取方法。它读取数据集以识别组,然后使用直接访问方法POINT =来提取相关记录。我提出了额外的条件,grp = lag(grp),以防你有任何只有1条记录的小组。
data want;
set have;
by grp;
if first.grp then do;
num_grp=0;
outflag=0;
end;
outflag+ifn(lag(first.grp)=1 and grp=lag(grp) and abs(dif(age))>5,1,0) /* set flag to determine if group meets criteria */;
if not first.grp then num_grp+1; /* count number of records in group */
if last.grp and outflag=1 then do i=_n_-num_grp to _n_;
set have point=i; /* extract required group records */
drop num_grp outflag;
output;
end;
run;
答案 3 :(得分:0)
这是一种SQL方法(使用CarolinaJay的代码创建数据集):
data groups1;
input id grp age sex $;
datalines;
1 1 60 M
2 1 21 M
3 2 30 M
4 2 25 F
5 3 45 F
6 3 30 F
7 3 18 M
8 4 32 M
9 4 18 M
10 4 16 M
;
run;
proc sql noprint;
create table xx as
select a.*
from groups1 a
where grp in (select b.grp
from groups1 b
join groups1 c on c.id = b.id+1
and c.grp = b.grp
and abs(c.age - b.age) > 5
left join groups1 d on d.id = b.id-1
and d.grp = b.grp
where d.id eq .
)
;
quit;
C上的联接查找所有出现的情况,其中同一组中的后续记录具有绝对值> 5. D(和where子句)的连接确保我们只考虑C连接的结果,如果记录是组中的第一个记录。
答案 4 :(得分:0)
data have;
input id $ grp $ age sex $;
datalines;
1 1 60 M
2 1 21 M
3 2 30 M
4 2 25 F
5 3 45 F
6 3 30 F
7 3 18 M
8 4 32 M
9 4 18 M
10 4 16 M
;
data want;
do i = 1 by 1 until(last.grp);
set have;
by grp notsorted;
if first.grp then cnt = 0;
cnt + 1;
if cnt = 1 then age1 = age;
if cnt = 2 then age2 = age;
diff = sum( age1, -age2 );
end;
do until(last.grp);
set have;
by grp;
if diff > 5 then output;
end;
run;