0

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

提前致谢。

4

5 回答 5

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;
于 2012-06-22T01:05:41.997 回答
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;
于 2012-06-22T13:50:15.603 回答
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;
于 2012-06-22T14:37:29.013 回答
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 连接的结果记录在群里。

于 2012-06-25T15:03:46.437 回答
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;
于 2012-06-27T03:24:45.940 回答