在SAS中,是否有一种简单的方法可以从出现次数超过2次的数据集中提取记录。
DUPS命令提供了重复项,但是如何获得三次重复项? 例如,在此数据集中:
col1 col2 col3 col4 col5
1 2 3 4 5
1 2 3 5 7
1 2 3 4 8
A B C D E
A B C S W
前3列是我的关键列。所以在我的输出中,我只想要前3行(三次)但不是最后2行(重复)
答案 0 :(得分:3)
我会使用proc sql
来利用group by
和having
条款。{p>即使它是代码的一个步骤,它确实需要在后台传递2次数据,但我相信无论您使用哪种方法都需要这样做。
data have;
input col1 $ col2 $ col3 $ col4 $ col5 $;
datalines;
1 2 3 4 5
1 2 3 5 7
1 2 3 4 8
A B C D E
A B C S W
;
run;
proc sql;
create table want as
select * from have
group by col1,col2,col3
having count(*)>2;
quit;
答案 1 :(得分:1)
你可以很容易地使用proc sql实现这一点。下面的示例将使表中的所有行保持一式三份(或更高)。
创建一些示例数据:
data have;
input col1 $
col2 $
col3 $
col4 $
col5 $
;
datalines;
1 2 3 4 5
1 2 3 5 7
1 2 3 4 8
A B C D E
A B C S W
;
run;
首先确定三次重复。我假设您需要一式三份(或以上),并且您要对前三列进行分组:
proc sql noprint;
create table tmp as
select col1, col2, col3, count(*)
from have
group by 1,2,3
having count(*) ge 3
;
quit;
然后使用我们刚创建的tmp表通过连接过滤原始数据集。
proc sql noprint;
create table want as
select a.*
from have a
join tmp b on b.col1 = a.col1
and b.col2 = a.col2
and b.col3 = a.col3
;
quit;
如果您愿意,可以将这两个步骤与子查询合并为一个步骤,但我会将其留给您。
编辑: Keith的回答提供了将这两个步骤合并为一个步骤的简便方法。
答案 2 :(得分:0)
这是数据步骤解决方案:一个双DoW循环,首先计算行然后在> = 3时输出。这实际上只在排序后传递一次数据(双DoW循环列出两次读取,但它们'重新缓冲,因此文件只读一次。)
这个解决方案在我的机器上的运行速度比SQL解决方案快一些;不是很多,而是略微。在具有12.5MM行的数据集中,其中大约1/4在最后的三重+数据集中,总时间(sort plus datastep)大约是10s real / 13.5s CPU,而Keith的SQL是12.5 real / 15 CPU。我怀疑这个解决方案总是比SQL解决方案稍微快一些,但在很多情况下速度并不快,除非您可以跳过排序但数据集实际上没有排序(如果数据集被标记,SQL将只跳过排序按照排序)。
NOUNIQUEKEY仅适用于9.3+,有时也很有帮助 - 如果你有很多独特的记录,只有很少的重复(2行以上),它会加速最后的阅读。但是,进行排序需要更长的时间,所以如果最终的读取加速有用,那么它是值得的。在下面它是非常有帮助的,但不是很多;它将执行从5s / 5s RT转换为6s / 3s,但是在相同的CPU时间--8 / 5.5(正常)和10.5 / 3(nounique)。
data have;
input col1 $ col2 $ col3 $ col4 $ col5 $;
datalines;
1 2 3 4 5
1 2 3 5 7
1 2 3 4 8
A B C D E
A B C S W
;;;;
run;
proc sort nouniquekey data=have out=have_dups; *nouniquekey is 9.3+, helps optimize sometimes- it is optional;
by col1 col2 col3;
run;
data want;
do _n_=1 by 1 until (last.col3);
set have_dups;
by col1 col2 col3;
count_row=sum(count_row,1);
end;
do _n_=1 by 1 until (last.col3);
set have_dups;
by col1 col2 col3;
if count_row ge 3 then output;
end;
run;