复制SAS中下面一行的值

时间:2014-10-30 23:32:15

标签: sas

我希望这不是一个重复的问题。我已经搜索了论坛并保留了功能似乎是武器的选择,但它复制了一个观察,我试图做以下事情;对于给定的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;

2 个答案:

答案 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)。