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;
我有这个数据库:
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;