使用SAS检测大于某个值的b / w年龄差异

时间:2012-06-21 20:26:16

标签: sas

我正在尝试检测包含第一年龄和第二年龄之间差异的组大于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;之类的内容获得年龄之间的绝对值。但我不知道如何按组分获得第一年龄和第二年龄之间的绝对值,或者实际上我不知道该如何开始这个。

提前致谢。

5 个答案:

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