使用SAS
数据集,例如
Ob x year pid grp
1 3.88 2001 1 a
2 2.88 2002 1 a
3 0.13 2004 1 a
4 3.70 2005 1 a
5 1.30 2007 1 a
6 0.95 2001 2 b
7 1.79 2002 2 b
8 1.59 2004 2 b
9 1.29 2005 2 b
10 0.96 2007 2 b
我想得到
Ob x year pid grp grp X_F1 XL1
1 3.88 2001 1 a a 2.88 .
2 2.88 2002 1 a a . 3.88
3 0.13 2004 1 a a 3.7 .
4 3.7 2005 1 a a . 0.13
5 1.3 2007 1 a a . .
6 0.95 2001 2 b b 1.79 .
7 1.79 2002 2 b b . 0.95
8 1.59 2004 2 b b 1.29 .
9 1.29 2005 2 b b . 1.59
10 0.96 2007 2 b b . .
对于具有相同pid
和每年t
的观察,
x_F1
是年x
和t+1
的值
x_L1
是年t-1
在我的数据集中,并非所有pid
都有连续几年的观察结果。
我尝试使用expand proc
proc expand data=have out=want method=none;
by pid; id year;
convert x = x_F1 / transformout=(lead 1);
convert x = x_F2 / transformout=(lead 2);
convert x = x_F3 / transformout=(lead 3);
convert x = x_L1 / transformout=(lag 1);
convert x = x_L2 / transformout=(lag 2);
convert x = x_L3 / transformout=(lag 3);
run;
没有考虑到年份不连续的事实。
答案 0 :(得分:3)
您可以坚持使用proc expand
将缺失的年份插入数据中(使用extrapolate
语句)。我已将from
值设置为day
,因为这是对数据进行的连续整数检查,因为YEAR存储为整数而不是日期。
与其他答案一样,它需要2次传递数据,但我不认为有替代方案。
data have;
input x year pid grp $;
datalines;
3.88 2001 1 a
2.88 2002 1 a
0.13 2004 1 a
3.70 2005 1 a
1.30 2007 1 a
0.95 2001 2 b
1.79 2002 2 b
1.59 2004 2 b
1.29 2005 2 b
0.96 2007 2 b
;
run;
proc expand data = have out = have1
method=none extrapolate
from=day to=day;
by pid;
id year;
run;
proc expand data=have1 out=want method=none;
by pid; id year;
convert x = x_F1 / transformout=(lead 1);
convert x = x_F2 / transformout=(lead 2);
convert x = x_F3 / transformout=(lead 3);
convert x = x_L1 / transformout=(lag 1);
convert x = x_L2 / transformout=(lag 2);
convert x = x_L3 / transformout=(lag 3);
run;
或者这可以一次完成,取决于x的值在最终数据集中是否重要(参见下面的评论)。
proc expand data=have1 out=want1 method=none extrapolate from=day to=day;
by pid; id year;
convert x = x_F1 / transformout=(lead 1);
convert x = x_F2 / transformout=(lead 2);
convert x = x_F3 / transformout=(lead 3);
convert x = x_L1 / transformout=(lag 1);
convert x = x_L2 / transformout=(lag 2);
convert x = x_L3 / transformout=(lag 3);
run;
答案 1 :(得分:2)
以下是使用proc sql
的简单方法。它将数据与自身连接两次;一次用于前向,一次用于后向滞后,然后取得它们存在的所需值。
proc sql;
create table want as
select
a.*,
b.x as x_f1,
c.x as x_l1
from have as a
left join have as b
on a.pid = b.pid and a.year = b.year - 1
left join have as c
on a.pid = c.pid and a.year = c.year + 1
order by
a.pid,
a.year;
run;
警告:
pid
year
对只有一个观察值,如果不是这样,则需要修改。 答案 2 :(得分:1)
if (year and lag(year) are consecutive) then x_F1=lag(x)
我现在正试着给你写一个正常工作的代码。 如果您向我提供数据样本(例如,带有infile的数据步骤),我可以尝试测试它。
这似乎适用于我的数据:
/*1*/
proc sort data=WORK.QUERY_FOR_EPILABO_CLEAN_NODUP out=test1(where=(year<>1996)) nodupkey;
by grp year;
run;
quit;
/*2*/
data test2;
*retain x;
set test1;
by grp;
x_L1=lag(x);
if first.grp then
x_L1=.;
yeardif=dif(year);
if (yeardif ne 1) then
x_L1=.;
run;
/*3*/
proc sort data=test2(drop=yeardif) out=test3;
by grp descending year;
run;
quit;
/*4*/
data test4;
*retain x;
set test3;
by grp;
x_F1=lag(x);
if first.grp then
x_F1=.;
yeardif=dif(year);
if (yeardif ne -1) then
x_F1=.;
run;