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

使用SAS检测大于某个值的b/w年龄差异,sas,Sas,我试图发现第一年龄组和第二年龄组之间的差异大于5。例如,如果我有以下数据,则grp=1中的年龄差为39,因此我希望在单独的数据集中输出该组。GRP4也是如此 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对它们

我试图发现第一年龄组和第二年龄组之间的差异大于5。例如,如果我有以下数据,则
grp=1
中的年龄差为39,因此我希望在单独的数据集中输出该组。GRP4也是如此

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之类的方法获得年龄之间的绝对值。但我不知道如何得到第一个年龄段和第二个年龄段之间的绝对值,或者实际上我不知道应该如何开始


提前谢谢。

我认为有一种方法是有效的

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;

我认为有一种方法是有效的

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;

我会使用PROC转置,这样每个组中的值都可以很容易地进行比较。例如:

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;
有了转置的数据,你可以做任何你喜欢的比较(我不能从你的问题中看出你到底想要什么,所以我只是比较前两个年龄段):

在本例中,这将是我的首选方法,用于为满足任何应用条件的每个组创建单独的数据集(动态生成并包含代码):


我会使用PROC转置,这样每个组中的值都可以很容易地进行比较。例如:

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;
有了转置的数据,你可以做任何你喜欢的比较(我不能从你的问题中看出你到底想要什么,所以我只是比较前两个年龄段):

在本例中,这将是我的首选方法,用于为满足任何应用条件的每个组创建单独的数据集(动态生成并包含代码):


如果您只关注第1个和第2个年龄段之间的差异,那么下面的代码是提取这些差异的一种相当简单的方法。它读取数据集以识别组,然后使用直接访问方法POINT=,提取相关记录。我加了一个额外的条件,grp=lag(grp),以防任何组只有一条记录

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;

如果您只关注第1个和第2个年龄段之间的差异,那么下面的代码是提取这些差异的一种相当简单的方法。它读取数据集以识别组,然后使用直接访问方法POINT=,提取相关记录。我加了一个额外的条件,grp=lag(grp),以防任何组只有一条记录

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;
下面是一种SQL方法(使用CarolinaJay的代码创建数据集):

C上的联接查找同一组中后续记录的绝对值大于5的所有实例。d(和WHERE子句)的连接确保我们只考虑C连接的结果,如果记录是组中的第一个记录。 下面是一种SQL方法(使用CarolinaJay的代码创建数据集):

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;

C上的联接查找同一组中后续记录的绝对值大于5的所有实例。d(和WHERE子句)的连接确保我们只考虑C连接的结果,如果记录是组中的第一个记录。 为了澄清,您是否对每组第一个和第二个年龄之间的差异感兴趣,或者对每组第一个和最后一个年龄之间的差异感兴趣?同样为了澄清,如果任何两个连续年龄(在一个组中)超过5岁,那么就捕获整个组?id顺序重要吗?请澄清,您是否对每组的第一个和第二个年龄或每组的第一个和最后一个年龄之间的差异感兴趣?还请澄清,如果任何两个连续年龄(在一个组中)超过5岁,则整个组都会被捕获?id顺序重要吗?恕我不同意,但是PROC转置根本不应该用于此类问题。你永远不知道每个组会有多少条记录,最后可能会有很多列。解决方案应该是合理通用的,不依赖于样本数据集。@CarolinaJay65使用RETAIN的解决方案是IMO的最佳选择。您是对的,创建的列的数量会有所不同,但我认为这正是Proc Transpose是一个好解决方案的原因。它获取所有列。列数的可变性可以通过数组来克服(__________;或_____;数值__________。你永远不知道每个组会有多少条记录,最后可能会有很多列。解决方案应该是合理通用的,不依赖于样本数据集。@CarolinaJay65使用RETAIN的解决方案是IMO的最佳选择。您是对的,创建的列的数量会有所不同,但我认为这正是Proc Transpose是一个好解决方案的原因。它获取所有列。列数的可变性可以用数组(_____________________;或__
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;