【问题标题】:Split dataset if variable value appears twice如果变量值出现两次,则拆分数据集
【发布时间】:2018-09-04 23:51:11
【问题描述】:

我想将一个数据集分成两个子集。我希望第一个子集包含 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;

【问题讨论】:

  • 将它发布到communities.sas.com 上,这样的问题您会得到更好的答复。最好的解决方案可能需要一个 HASH 或 DoW 循环,这可能仍然是数据的两次传递,尽管可能更有效。我添加了一个分号 - 您的数据步骤缺少正确运行。

标签: sas proc-sql


【解决方案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 对象在单次数据传递中生成两个重复列表。

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

【讨论】:

  • 那不行,ID 1 应该是多个,因为 ID 再次出现在第三行。
  • 我重新设计了答案以解决两个独立 id 变量的问题。
【解决方案2】:

我认为一个视图可能有效,但它肯定是更多的通行证,而且效率肯定更低。 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 之间具有一对一的对应关系。另一个数据集应该有其他行(多对一、多对多、一对多)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-10
  • 2018-08-25
  • 1970-01-01
  • 2019-04-08
  • 1970-01-01
  • 2018-09-25
相关资源
最近更新 更多