这是数据集的一部分:
Obs Buffer
...
75 14
76 13
77 64
78 38.1%
79 29.2%
80 69.2%
81 33
82 5-12
...
我只需要包含“%”的数据和前面的两行。例如,在这种情况下,我想拉出“13”“64”“38.1%”“29.2%”和“69.2%”。
有没有办法可以做到这一点?
我喜欢用point
这种东西。 _N_
只要您没有对数据步骤循环做任何有趣的事情,它作为行计数器是可靠的。
data have;
length buffer $50;
input obs buffer $;
datalines;
75 14
76 13
77 64
78 38.1%
79 29.2%
80 69.2%
81 33
82 5-12
;;;;
run;
data want;
set have;
pointer=_N_;
if find(buffer,'%') then do;
output;
pointer=_N_-1;
set have point=pointer;
if not (find(buffer,'%')) then do;
output;
pointer=_N_-2;
set have point=pointer;
if not (find(buffer,'%')) then output;
end;
end;
run;
如果您需要恢复您的订单,您可以在pointer
之后进行排序(或者obs
,如果这是一个真正的变量 - 我认为它不是)。如果obs
确实是一个真正的变量(或者如果你用视图使它成为真实的),SQL 中有一种有趣的方法可以做到这一点:
proc sql;
create table want as
select H.* from have H
left join have V on H.obs=V.obs-1
left join have A on H.obs=A.obs-2
where
(find(H.buffer,'%'))
or
(find(V.buffer,'%'))
or
(find(A.buffer,'%'))
order by H.obs
;
quit;
如何在没有数据传递的情况下使 obs 真实:
data have_vw/view=have_vw;
set have;
obs=_n_;
run;
然后在 SQL 查询中使用have_vw
而不是have
(在所有三个位置)。
回答您的问题:_N_
变量将返回数据步骤循环通过数据语句的次数。(http://support.sas.com/documentation/cdl/en/lrcon/62955/HTML/default/viewer.htm#a000695104.htm)
但是,要解决您的问题,请使用lag()
(http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212547.htm)和包含语句,例如
data justBuffers;
set yourDS;
twoBefore = lag2(Buffer);
oneBefore = lag1(Buffer);
if Buffer ? '%' then do;
if not missing(twoBefore) then do;
x = twoBefore;
output;
end;
if not missing(oneBefore) then do;
x = oneBefore;
output;
end;
x = Buffer;
output;
call missing(oneBefore, twoBefore);
end;
keep x;
run;
我没有测试过代码,所以要小心!我相信你可以让它更顺畅。
通过遵循 kungfujam 的想法,我得到了下面的代码并且它可以工作。
data adjust;
set source;
oneBefore = lag1(Buffer);
twoBefore = lag2(Buffer);
threeBefore = lag3(Buffer);
fourBefore = lag4(Buffer);
if index(buffer,'%')^=0 and index(onebefore,'%')^=0 and index(twobefore,'%')^=0then do;
x = fourBefore;
output;
x = threeBefore;
output;
x = twoBefore;
output;
x = oneBefore;
output;
x=buffer;
output;
end;
keep x;
run;