从SAS中的下一行复制值

从SAS中的下一行复制值,sas,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 ha

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

在SAS中,Lead很棘手。您可以反向排序并使用滞后函数绕过它,您是对的: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;

如果您的数据完全如您所说,那么您可以使用前瞻性合并。它从字面上获取数据集并将自身合并到从第2行开始的数据集副本中,并排合并。您只需检查您是否仍然在同一个ID上。这会将所有记录的x值更改为1,而不仅仅是第一个;您可以添加额外的代码来注意这一点(但不能使用FIRST和LAST)

如果您没有任何其他感兴趣的变量,那么您可以做一些更有趣的事情:完整复制第二行并删除第一行

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;
然而,“最安全”的方法(就最有可能做你想做的事情而言)是以下方法,这是道指循环

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(按组),然后在第二个循环中将其设置为第1行和输出的正确值


在后面的两个示例中,我假设您的数据是按ID组织的,但不是真正排序的(就像您最初的示例一样)。如果它不是按ID组织的,您需要先执行排序(但可以删除NOTSORTED)。

您有SAS/ETS软件包吗?如果是这样的话,Proc Expand和lead转换可能会有所帮助。
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;