我希望根据当前行的值有条件地更改上一行中变量的值。
对于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
。
话虽如此,我知道为什么这不起作用。请记住,我是一名初学程序员,并且不了解先前提出的类似问题的代码。
谢谢!
答案 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匹配。