如果变量值出现两次则拆分数据集
Split dataset if variable value appears twice
我想将一个数据集分成两个子集。我希望第一个子集包含 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;
您的代码对数据进行了 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 对象在数据的单次传递中生成两个重复列表。
然后您可以将它们写回并使用上面的数据步骤进行拆分。或者只是让创建哈希对象的步骤再次重新读取数据集。
我认为一个视图可能会起作用,但它肯定会通过更多次并且效率肯定会更低。 DoW 循环可能是更好的解决方案,至少只有两次通过,这个可能至少需要 4 次!在线查询肯定效率较低。
虽然是个有趣的问题。如果您解释一些上下文,它也可能会有所帮助,也许有更简单的方法可以以某种方式解决此问题?
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;
我想将一个数据集分成两个子集。我希望第一个子集包含 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;
您的代码对数据进行了 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 对象在数据的单次传递中生成两个重复列表。
然后您可以将它们写回并使用上面的数据步骤进行拆分。或者只是让创建哈希对象的步骤再次重新读取数据集。
我认为一个视图可能会起作用,但它肯定会通过更多次并且效率肯定会更低。 DoW 循环可能是更好的解决方案,至少只有两次通过,这个可能至少需要 4 次!在线查询肯定效率较低。
虽然是个有趣的问题。如果您解释一些上下文,它也可能会有所帮助,也许有更简单的方法可以以某种方式解决此问题?
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;