有条件地改变前一行的值

时间:2017-08-23 18:52:46

标签: sas

我希望根据当前行的值有条件地更改上一行中变量的值。

对于status = 1的所有行,我希望上一行中的状态也等于1.

以下是一个示例数据集:

ID Status
1    0
1    1
1    1 
2    0
2    1
2    0
2    0
2    1

我想要的是:

ID Status
1    1
1    1
1    1 
2    1
2    1
2    0
2    1
2    1

我想要的代码是这样的:

if status=1 then lag(status)=status;

请注意,我的所有first.id都有status=0

话虽如此,我知道为什么这不起作用。请记住,我是一名初学程序员,并且不了解先前提出的类似问题的代码。

谢谢!

2 个答案:

答案 0 :(得分:0)

如果为原始行号(_n_)添加变量,则可以使用descending将数据集按相反顺序排序,然后使用滞后运算符:

data one;
 infile cards;
 input id status;
 sequence=_n_;
cards;
1 0
1 1
1 1 
2 0
2 1
2 0
2 0
2 1
;
run;

proc sort data=one;
 by id descending sequence;
run;

我不确定您是否希望以前的值包含ID。如果ID不同(not first.id),此示例不会查看滞后值。

data two;
 set one;
 by id descending sequence;
 if not first.id and lag(status) = 1 then status=1;
run;

proc sort data=two;
 by id sequence;
run;

答案 1 :(得分:0)

您可以将其视为前瞻性问题,而不是将其视为更改前一行。也就是说,当您阅读每条记录时,您希望查看下一条记录,以查看状态值是否为1。

展望未来的一种方法是将数据集与自身合并。这有点棘手,但对于想要理解DATA步骤的初学者来说,这是一个很好的教训。如果合并两个没有BY语句的数据集,它们将按顺序一起刷新(从每个数据读取的第一个记录合并在一起,然后从每个数据读取第二个记录,等等)。如果您将数据集与自身合并,并且第二次开始阅读第二次观察,则您有一个前瞻。这是一个艰难的句子,但使用你的样本数据:

options mergenoby=nowarn ;

data lookahead ;
  merge have
        have (keep=status rename=(status=NextStatus) firstobs=2)
  ;
run ;

options mergenoby=error ;

因此,第二次读取数据集时,firstobs选项会在第二次观察时开始读取,并且只读取STATUS变量,并将其重命名为NextStatus。结果是:

                         Next
 Obs    id    status    Status

  1      1       0         1
  2      1       1         1
  3      1       1         0
  4      2       0         1
  5      2       1         0
  6      2       0         0
  7      2       0         1
  8      2       1         .

花点时间了解上面的步骤,并稍微玩一下。 MERGENOBY选项控制当合并步骤中没有BY时,SAS是否抛出错误,警告或无警告。我总是将MERGENOBY设置为错误,因为99%的时间如果合并步骤没有BY语句,那么这是一个偶然的遗漏。当我故意与no合并时,我在步骤之前设置MERGENOBY = NOWARN,然后立即返回MERGENOBY = ERROR。一旦你理解了它的工作方式,你所需要的就是获得你想要的输出。

options mergenoby=nowarn;

data want;
  merge have
        have (keep=status rename=(status=NextStatus) firstobs=2)
  ;
  if NextStatus=1 then Status=1;
  drop NextStatus;
run;

options mergenoby=error;


Obs    id    status

 1      1       1
 2      1       1
 3      1       1
 4      2       1
 5      2       1
 6      2       0
 7      2       1
 8      2       1

请注意,这是一个简单的预测,它将展望值。因此,如果您有状态= 0的ID的最后一条记录,以及状态为1的下一个ID的第一条记录,它会将状态重置为1.如果您不想要,则可以添加逻辑检查NextID是否与当前ID匹配。