我希望这不是一个重复的问题。我已经搜索了论坛并保留了功能似乎是武器的选择,但它复制了一个观察,我试图做以下事情;对于给定的id,将第二行复制到x值的第一行。 x的第一个值也总是2.
这是我的数据;
id x
3 2
3 1
3 1
2 2
2 1
2 1
6 2
6 0
6 0
我希望它看起来像这样;
id x
3 1
3 1
3 1
2 1
2 1
2 1
6 0
6 0
6 0
这是首发代码;
data have;
input id x;
cards;
3 2
3 1
3 1
2 2
2 1
2 1
6 2
6 0
6 0
;
run;
答案 0 :(得分:2)
SAS中的铅很棘手。你可以反过来排序并使用滞后函数绕过它,你是对的:一个retain语句允许我们添加一个order变量,这样我们就可以将它排序回原来的格式。
data have;
set have;
retain order;
lagid = lag(id);
if id ne lagid then order = 0;
order = order + 1;
drop lagid;
run;
proc sort data=have; by id descending order; run;
data have;
set have;
leadx = lag(x);
run;
proc sort data=have; by id order; run;
data have;
set have;
if order = 3 then x_fixed = x;
else x_fixed = leadx;
run;
答案 1 :(得分:0)
如果您的数据完全如您所说,那么您可以使用前瞻合并。它实际上采用数据集并将自身合并到从第2行开始,并排放置的数据集的副本。您只需检查您是否仍然使用相同的ID。这确实将所有记录的x值更改为值1,而不仅仅是第一个值;你可以添加额外的代码来注意(但不能使用FIRST和LAST)。
data want;
merge have have(firstobs=2 rename=(id=newid x=newx));
if newid=id then x=newx;
keep x id;
run;
如果您没有任何其他感兴趣的变量,那么您可以做一些更有趣的事情:完整复制第二行并删除第一行。
data want;
set have;
by id notsorted;
if first.id then do;
firstrow+1;
delete;
end;
if firstrow=1 then do;
firstrow=0;
output;
end;
output;
run;
但是,最安全的"方法(就最有可能完全按照你想要的方式而言)是以下,这是一个DoW循环。
data want;
idcounter=0;
do _n_ = 1 by 1 until (last.id);
set have;
by id notsorted;
idcounter+1;
if idcounter=2 then second_x = x;
end;
do _n_=1 by 1 until (last.id);
set have;
by id notsorted;
if first.id then x=second_x;
output;
end;
run;
这标识第一个循环中的第二个x,对于该BY组,然后在第二个循环中将其设置为第1行和输出的正确值。
在后两个示例中,我假设您的数据按ID进行组织,但没有真正排序(就像您的初始示例一样)。如果它没有按ID组织,您需要先执行排序(但可以删除NOTSORTED)。