如何在SAS中提取一式三份或更高的记录

时间:2015-07-09 14:41:11

标签: sql sas

在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行(重复)

3 个答案:

答案 0 :(得分:3)

我会使用proc sql来利用group byhaving条款。{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;