需要更改以前的值

时间:2013-12-03 10:13:19

标签: sas

假设我们有以下数据集

obs    check   result
---------------------
aa     0       0
bb     0       0
cc     1       0
dd     0       0
ee     1       1 
ff     1       1 <- we are here. Due to prev. value both eq 1 the "result" variable for both of them should also be 1

我需要的是检查连续“check”变量中的2个或更多个案例是否等于1,如果是这样,那么两个“result”变量也应该是1.问题是唯一的方法我看到将“result”设置为1,因为它们都以某种方式返回到之前的“观察行”并将“result”变量更改为1。

2 个答案:

答案 0 :(得分:3)

由于数据步骤循环的设计方式,我认为我们不能轻易回到之前的观察。但是,我们可以使用retain语句和merge数据集与自己withoutby语句来访问上一个或下一个观察结果:

data work.sample;
    input obs $ check result;
    retain x;
    output;
    x = check;
    datalines;
    aa     0       0 
    bb     0       0
    cc     1       0
    dd     0       0
    ee     1       0 
    ff     1       0
    ;
run;

data work.sample2;
    merge work.sample
    work.sample(firstobs = 2 keep = check 
    rename = (check = c));
    if (check = 1 and x = 1) or (check = 1 and c = 1) then result = 1; 
run;

OUTPUT看起来像这样:

                      Obs    obs    check    result    x    c

                       1     aa       0         0      .    0
                       2     bb       0         0      0    1
                       3     cc       1         0      0    0
                       4     dd       0         0      1    1
                       5     ee       1         1      0    1
                       6     ff       1         1      1    .

因此,变量x表示使用retain语句和output语句保留的值。变量c表示我们在观察= 2时将数据集与自身合并时创建的变量。

最后,如果连续出现check = 1,我们会使用条件语句将新值放入结果变量。

答案 1 :(得分:2)

Yick的答案是一种非常好的通用方法,但这个具体问题有一个有趣,简单的答案。

SAS有一种方法可以向前看,而不必以某种方式第二次读取数据:使用LAST.<variable>语句创建的BY自动变量。这些涉及SAS的自动前瞻,而不会强迫您手动完成。感谢NOTSORTED,这可以让您查看下一个值是否恰好等于变量的当前值。

使用Yick的数据集:

data work.sample;
    input obs $ check result;
    retain x;
    output;
    x = check;
    datalines;
    aa     0       0 
    bb     0       0
    cc     1       0
    dd     0       0
    ee     1       0 
    ff     1       0
    ;
run;

data want;
set sample;
by check notsorted;
if not (first.check and last.check) and (check=1) then result=1;  
*if it is not the first record AND the last record with the same check value in a row,
 then it is one of a sequence of two or more and if check=1 then result should be 1;
put _all_;
run;