SAS:按 ID 重复最后一个值

SAS: repeat the last value by ID

我有这个数据库:

data temp;
input ID date type ;
  datalines;
 1 10/11/2006   1      
 1 10/12/2006   2      
 1 15/01/2007   2      
 1 20/01/2007   3    
 2 10/08/2008   1        
 2 11/09/2008   1        
 2 17/10/2008   1        
 2 12/11/2008   2    
 2 10/12/2008   3       
 ;

我想创建一个新列,其中我按 ID 重复最后一个日期:

data temp;
input ID date type  last_date;
  datalines;
 1 10/11/2006   1        20/01/2007
 1 10/12/2006   2        20/01/2007
 1 15/01/2007   2        20/01/2007
 1 20/01/2007   3        20/01/2007
 2 10/08/2008   1        10/12/2008
 2 11/09/2008   1        10/12/2008
 2 17/10/2008   1        10/12/2008
 2 12/11/2008   2        10/12/2008
 2 10/12/2008   3        10/12/2008
 ;

我试过这段代码,但它不起作用:

  data temp;
  set temp;
  IF last.ID then last_date= .;
  RETAIN last_date;
  if   missing(last_date) then last_date= date;
  run;

提前感谢您的帮助!

首先,FIRST.ID 和 LAST.ID 变量不会在数据步骤中创建,除非您在 BY 语句中包含变量 ID。

其次,要将最后日期附加到每个观察结果中,您需要对数据进行两次处理。您当前的代码(如果添加了 BY 语句)只会在 by 组的最后一次观察时为 LAST_DATE 赋值。

一种方法是在每个组中按日期降序对数据重新排序,然后您可以使用 BY ID 和 FIRST.ID 和 RETAIN。

proc sort data=have;
   by id descending date;
run;
data want;
   set have;
   by id descending date;
   if first.id then last_date=date;
   retain last_date;
   format last_date ddmmyy10.;
run;

这是一种使用原始排序顺序的方法,使用所谓的双 DOW 循环。通过将 SET/BY 语句放在 DO 循环中,您可以在数据步骤的单次传递中读取一组的所有观察结果。然后添加第二个 DO 循环以重新处理该 BY 组并使用在第一个循环中计算的信息并写出观察结果。

data want;
do until (last.id);
  set have;
  by id;
end;
last_date=date ;
format last_date ddmmyy10.;
do until (last.id);
  set have;
  by id; 
  output;
end;
run;

其他两种方式是:

  • Proc SQL 加入子选择,或
  • Proc MEANS + DATA/MERGE

SQL

 proc sql;
   create table want as
   select have.*, id_group.max_date as last_date format=ddmmyy10.
   from
     have
   join 
     ( select id, max(date) as max_date
       from have
       group by id
     ) as id_group
   on
     have.id = id_group.id
   ; 

意思

proc means noprint data=have;
  by id;
  var date;
  output out=maxdates(keep=id last_date) max(date)=last_date;
run;

data want;
  merge have maxdates;
  by id;
run;