如果变量值出现两次,则拆分数据集

时间:2018-09-04 23:51:12

标签: sas proc-sql

我想将数据集分为两个子集。我希望第一个子集包含id或id1的值出现多次的所有行。

为此,

data test;
input id id1 var1 $ var2 $;
datalines;
1 11 A B
2 22 C D
3 11 E F
3 12 G H
7 15 K L
3 13 M N
2 10 I J
8 16 P L
;;;;
run;

我希望子集成为

1 11 A B
2 22 C D
3 11 E F
3 12 G H
3 13 M N
2 10 I J

7 15 K L
8 16 P L

我可以使用下面的代码,但效率不高,因为拆分时有两次遍历数据集。还有其他选择吗?

proc sql;
create table DuplicateId as
select id from test
group by id
having count(id) > 1;
quit;

proc sql;
create table DuplicateID1 as 
select id1 from test
group by id1
having count(id1) > 1;
quit;

proc sql;
create table split1 as 
select * from test 
where id not in (select id from DuplicateID) and id1 not in (select id1 from DuplicateID1);
quit;

proc sql;
create table split2 as
select * from test
where id in (select id from DuplicateID) or id1 in (select id1 from DuplicateID1);
quit;

2 个答案:

答案 0 :(得分:1)

您的代码通过数据进行了4次传递。分别查找每个单独的ID变量的唯一(或重复)代码。每个输出数据集各一个。您可以使用索引查找将最后一步减少到一个步骤。

proc sql ;
create table dup1 (index=(id)) as
  select id from test
  group by 1 having count(*) > 1
;
create table dup2 (index=(id1)) as
  select id1 from test
  group by 1 having count(*) > 1
;
quit;
data single multiple;
  set test;
  set dup1 key=id / unique;
  if _iorc_ then set dup2 key=id1 / unique;
  if _iorc_ then output single;
  else output multiple;
  _error_=0;
run;

如果重复ID的列表足够小,可以存储在内存中,则可以使用HASH对象在一次数据传递中生成两个重复列表。

然后可以将它们写回,并使用上面的数据步骤进行拆分。或者只是执行创建散列对象的步骤,再次重新读取数据集。

答案 1 :(得分:0)

我认为一个视图可能有用,但是肯定是通过的次数更多,效率也更低。 DoW循环可能是一个更好的解决方案,至少只有两遍,这可能最少四遍!内联查询肯定效率较低。

有趣的问题。如果您解释一些上下文也可能有所帮助,也许有一种更简便的方法可以某种方式解决此问题?

proc sql;
    create view test2 as select *, (select count(_a1.ID) from test as _a1 where 
        _a1.id=t1.id group by id) as count1, (select count(_a2.ID1) from test as _a2 
        where _a2.id1=t1.id1 group by id1) as count2 from test as t1 order by 1, 2;
quit;

data single multiple;
    set test2;

    if max(count1, count2)>1 then
        output multiple;
    else
        output single;
run;